_CrtCheckMemoryのエラーについて

このQ&Aのポイント
  • 現在、あるプログラムのヒープ破壊と思われるエラーで悩んでおり、VC++のヒープチェック機能でデバッグしようとしています。
  • ちょっと摘み食いするだけのつもりでしたので、GNUMAKEをそのまま使ってコンパイルしているのですが、なぜかヒープ破壊の検出がうまくいかないようです。
  • どなたか、ご教授願います。環境は、Win7 Home 32bit、visual studio community 2017、Mingw
回答を見る
  • ベストアンサー

_CrtCheckMemoryのエラーについて

現在、あるプログラムのヒープ破壊と思われるエラーで悩んでおり、VC++のヒープチェック機能でデバッグしようとしています。 メイン開発ツールはMingwなのですが、AddressSanitizerなどが未実装のようなので、ヒープチェックのためだけにVisual Studio Communityを導入しました。 ちょっと摘み食いするだけのつもりでしたので、GNUMAKEをそのまま使ってコンパイルしているのですが、なぜかヒープ破壊の検出がうまくいかないようです。 期待しているのは、ヒープチェックのAssertでヒープ破壊のタイミングを見つけることです。 他のサイトの情報を見ると、Assertが引っかかったタイミングで、ちゃんとソースファイル名と行番号が表示されるはずなのですが、なぜか以下のような情報を吐くだけで、CrtCheckMemoryのソース?が挙げられるだけです。 Debug Assertion Failed! File: debug_heap.cpp Line: 280 Expression _CrtCheckMemory() 問題を切り分けるため、ヒープ破壊するだけの「CrtCheckMemory_TEST.c」をつくり、以下のコマンドでコンパイルしましたが、結果は同じでした。 "C:\Program Files\Microsoft Visual Studio\2017\Community\VC\Auxiliary\Build\vcvarsall.bat" x86 cl.exe /DUNICODE /D_UNICODE /D_DEBUG /MTd /c /FoCrtCheckMemory_TEST.obj CrtCheckMemory_TEST.c cl.exe /D_DEBUG /MTd /FeCrtCheckMemory_TEST.exe CrtCheckMemory_TEST.obj 1つ目は、コマンドラインからコンパイルするための環境変数を設定するバッチファイルを起動しています。 2つめは、UNICODE指定とデバッグフラグを立てて、/MTd(これがチェックのためのライブラリだと思っています。)オプションでオブジェクトファイルを作っています。 3つめは実行ファイルを生成しています。 なにか、オプションの指定し忘れなどがあるのでしょうか。 どなたか、ご教授願います。 環境は、Win7 Home 32bit、visual studio community 2017、Mingw 以下に、問題のソースを載せておきます。 #include <tchar.h> #include <stdio.h> #include <locale.h> #if defined (_MSC_VER) && (_DEBUG) #define _CRTDBG_MAP_ALLOC #include <stdlib.h> #include <crtdbg.h> #endif int main(int argc, char **argv){ TCHAR *text; setlocale( LC_ALL, "Japanese" ); #if defined (_MSC_VER) && (_DEBUG) _CrtSetDbgFlag(_CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF | _CRTDBG_CHECK_ALWAYS_DF ); _tprintf( _T("_CrtSetDbgFlag()実行\n") ); #endif if(argc>1){ printf( "argv=%s\n", argv[0] ); } text = malloc(10); _tprintf( _T("メモリ破壊開始\n") ); text[-6] = 7; _tprintf( _T("メモリ破壊終了\n") ); _ASSERTE( _CrtCheckMemory( ) ); return 0; }

質問者が選んだベストアンサー

  • ベストアンサー
  • myuki1232
  • ベストアンサー率57% (97/170)
回答No.1

やりたいことは、最後の行の _ASSERTE で止まって、その行数・ファイル名を表示してほしいということでしょうか? でしたら、原因は _CrtSetDbgFlag に _CRTDBG_CHECK_ALWAYS_DF フラグを指定していることです。 _CRTDBG_CHECK_ALWAYS_DF フラグを指定していると、メモリの確保・開放時に常に _CrtCheckMemory のチェックをするため、 _ASSERTE の前の _tprintf(_T("メモリ破壊終了\n")); の中で行われているヒープ確保・開放処理で止まってしまいます。 もし _CRTDBG_CHECK_ALWAYS_DF フラグを使うのであれば、VC++ のデバッガや windbg を使ってスタックトレースなどから発生箇所を追跡できるようにすべきでしょう。

kolona
質問者

お礼

ありがとうございます。 道理で、わけのわからないライブラリでエラーを検出するわけですね・・・ フラグの意味を完全に誤解していました。 問題の位置を特定できました。

関連するQ&A

  • 一部コマンドでエラー

    以下のプログラムにパス検索機能を追加しろ。 /bin/lsと入力していたものを、lsだけで実行できるようにする。 そのほかにもdata -Iやgcc -o test test.c、./testを実行可能にする。 と言う課題で、 if(execv(argv[0],argv[])==(-1)){をif(execvp(argv[0],argv)==(-1)){とする方法を聞いたのですが、 gcc -o test test.cを入力すると長文のエラーが出力されます。 どうしたら良いでしょうか? #include <stdio.h> #include <stdlib.h> #include <string.h> #include <unistd.h> main(int argc, char *argv[]){ int len, pid, st; char *p; int i, sp_flag; static char prompt[64]="> "; char command[256]; printf("%s",prompt); while (fgets(command, 256, stdin) != NULL){ if((len = strlen(command)) == 1)break; command[len-1] = '\0'; p=(char *)&command; sp_flag=0; for(i=0; *p!='\0';p++){ if(sp_flag == 0 && *p!=' '){ argv[i]=p; sp_flag=1; i++; }else if(*p==' '){ *p='\0'; sp_flag=0; } } argv[i]=(char *)0; for(i=0; argv[i]!=(char *)0; i++){ printf("%s\n",argv[i]); } if((pid = fork()) == 0){ if(execv(argv[0],argv)==(-1)){ printf("%s", "exec error.\n"); exit(1);} } else if(pid >= 1){ wait(&st); printf("%s", prompt); } else { perror("fork"); exit(1); } } exit(0); }

  • fatal error C1083: include ファイルを開けません というエラーが出ます

    初心者です。ソースは以下の通りです。 #include "stdafx.h" #include <cv.h> #include <highgui.h> #pragma comment(lib,"cv.lib") #pragma comment(lib,"cxcore.lib") #pragma comment(lib,"highgui.lib") int _tmain(int argc, _TCHAR* argv[]) { Ip1Image* img; //画像変数宣言 cvNamedWindow("画像表示"); // 表示ウィンドウの作成 img = cvLoadImage("Image.jpg"); //画像ファイルの読み込み if(img == NULL){ //ファイルが読み込めない場合 printf("ファイルが読み込めません。\n"); cvWaitKey(0); //キー入力待機 return -1; } cvShowImage("画像表示", img); //表示ウィンドウに画像を表示 cvWaitKey(0); //キー入力待機 cvDestroyWindow("画像表示"); //表示ウィンドウの破棄 cvReleaseImage(&img); //画像領域の解放 return 0; } 以上のソースをビルドすると、以下のようなエラーが出てしまって、うまくコンパイルすることができません。 1>------ ビルド開始: プロジェクト: ImageDisplay, 構成: Debug Win32 ------ 1>コンパイルしています... 1>ImageDisplay.cpp 1>c:\users\g031f096\documents\visual studio 2008\projects\imagedisplay\imagedisplay\imagedisplay.cpp(5) : fatal error C1083: include ファイルを開けません。'cv.h': No such file or directory 1>ビルドログは "file://c:\Users\g031f096\Documents\Visual Studio 2008\Projects\ImageDisplay\ImageDisplay\Debug\BuildLog.htm" に保存されました。 1>ImageDisplay - エラー 1、警告 0 ========== ビルド: 0 正常終了、1 失敗、0 更新不要、0 スキップ ========== どのようにすれば通るのでしょうか?よろしくお願いします。開発環境は Visual C++ 2008 Express Editionです。

  • 実行結果をコマンドライン引数として渡す方法について

    test1.cはコマンドラインから引数をとり処理するプログラム test2.cは「Hello!」と出力するプログラム。 これらのプログラムをコンパイルして、次のような引数の渡し方をしてHello!と表示したいのですがうまくいきません。 実際の結果 ----------------------------------------- $ ./test1.exe ./test2.exe ($はプロンプト) $ ./test2.exe $ ----------------------------------------- 期待する結果 ----------------------------------------- $ ./test1.exe ./test2.exe $ Hello! $ ----------------------------------------- ここでプログラムの仕様を示しておきます。 プログラム1(test1.c)の中身 -------------------------------------- #include <stdio.h> main(int argc, char *argv[]){ printf("%s\n", argv[1]); } -------------------------------------- プログラム2(test2.c)の中身 -------------------------------------- #include <stdio.h> main(){printf("Hello!\n");} -------------------------------------- よろしくお願いします!

  • C言語、度々申し訳ございません。エラーです。

    いつも大変お世話になり誠にありがとうございます。 標記の件。 コードとコンパイルエラーを書きます。 度々すいません。 どうしたらいいでしょうか? ご回答の程宜しくお願い申し上げます。            高橋耕造 1.コード #include <studio.h> int main(void) { printf("%d\n",123); printf("\\100もらった\n"); printf("またあした\n"); return 0; } 2.コンパイルエラー C:\MinGW>gcc test2.c -o test2 test2.c:1:20: fatal error: studio.h: No such file or directory #include <studio.h> ^ compilation terminated. 検索しましたが解りません。 ご回答の程宜しくお願い申し上げます。

  • ポインタのポインタ

    #include <stdio.h> #include <stdlib.h> #include <string.h> int main(int argc, char **argv){ int i; if(argc != 2) { fprintf(stderr, "Usage: %s vector\n\tEx: %s 11110000\n", argv[0], argv[0]); return 1; } for(i=0;i<8;i++){ if(**argv == '0'){ printf("%d\n",i); } else{ printf("A%d\n",i); } argv++; } return 0; } コンパイルして./a.exe 10010011などと入力しても A0 A1 Segmentation Faultとなります。 どうすれば、 A1 0 ・・・省略 for文で回した8回分、出力が可能になるのか教えてください。 初歩的な質問ですいません。

  • 'strcpy': 識別子が見つかりません

    またもやわからないことが・・・ Visual C++ 2005で以下は(一部なんですが)をコンパイルすると、 #include<stdio.h> #include<stdlib.h> FILE *fp; struct meibo{ char name[12]; double tokutenA[6]; double tokutenB[6]; }; void main(int argc,char *argv[]) { char fname[20]; printf("ファイル名\n"); scanf("%s",fname); strcpy(fname,argv[1]); void input(FILE *fp,struct meibo* a,int* end); struct meibo a[5]; FILE *fp; int ban,end; if((fp=fopen("d:\\test\\fname","w"))==NULL){ printf("開けません\n"); exit(1); } visual studio 2005\projects\meibo\meibo1.cpp(18) : error C3861: 'strcpy': 識別子が見つかりませんでした となります、どう言うことでしょうか。 よろしくお願いします。

  • 'strcpy': 識別子が見つかりません

    初心者でまたもやわからないことが・・・ Visual C++ 2005で以下は(一部なんですが)をコンパイルすると、 #include<stdio.h> #include<stdlib.h> FILE *fp; struct meibo{ char name[12]; double tokutenA[6]; double tokutenB[6]; }; void main(int argc,char *argv[]) { char fname[20]; printf("ファイル名\n"); scanf("%s",fname); strcpy(fname,argv[1]); void input(FILE *fp,struct meibo* a,int* end); struct meibo a[5]; FILE *fp; int ban,end; if((fp=fopen("d:\\test\\fname","w"))==NULL){ printf("開けません\n"); exit(1); } visual studio 2005\projects\meibo\meibo1.cpp(18) : error C3861: 'strcpy': 識別子が見つかりませんでした となります、どう言うことでしょうか。 よろしくお願いします。

  • コマンドライン引数argv[]について

    C言語初心者です。以下のようなプログラムを書いたのですが、コンパイルで来ません。関数func1, func2を分けずに全てメインに書けば動作するのですが、なぜ関数に分けてしまうとコンパイル出来ないのかがわかりません。エラー内容は、argvが宣言されていない、といった内容です。 #include <stdio.h> void func1(void){ printf("%s\n", argv[1]); } void func2(void){ printf("%s\n", argv[2]); } int main(int argc, char *argv[]){ if(strcmp(argv[1], "abc")==0){ func1(); } else{ func2(); } }

  • エラーがでてしまいます

    以下のプログラムなのですが、引数を与えると下のようなエラーになります。 #include<stdio.h> #include<stdlib.h> int main(int argc, char** argv) { FILE *in ,*out; unsigned char ch; if(argc != 3) { printf("入力エラーです。\n"); exit(1); } if((in = fopen(argv[1],"rb")) == NULL) { printf("入力ファイルが開けません。\n"); exit(1); } if((out = fopen(argv[2],"rb")) == NULL) { printf("出力ファイルが開けません。\n"); exit(1); } while(!feof(in)) { ch = fgetc(in); if(!feof(in)) fputc(~ch,out); } fclose(in); fclose(out); return 0 ; } tyobi@tyobi-laptop:~$ gcc test.c diary copy diary: file not recognized: File format not recognized collect2: ld はステータス 1 で終了しました どうしたらよいのでしょうか?

  • インクルードパスを相対パスで指定

    Visual C++ 2017を使用したプロジェクト開発で、次のようなディレクトリ構造になっているとします。 root/  └ dev/    └ L1/      ├ L2/      │ ├ L3/      │ │ └ L4/      │ │   └ MyProj(開発用ディレクトリ)      │ └ foo/      │      └ include/ プロジェクトファイルやソースファイルは全てMyProjの直下にあります。 L2と同じ階層にあるincludeディレクトリにあるtest.hをソースファイルにインクルードするために、次のような#include文を記述します。 #include "../../../include/test.h" これで問題なくコンパイルが通ります。 次に、プロジェクトのプロパティの「追加のインクルードディレクトリ」に"../../foo"を追加します。 これは次のようなオプションと解釈されてコンパイラに渡されます。 /I"../../foo" fooというディレクトリのみを参照パスに追加するつもりで、プロジェクトファイルからの相対パスで指定しました。 さてここで#include文を次のように書き換えてみました。 #include "../../include/test.h" これでコンパイルが通るのです。 ソースファイルからtest.hへの相対パスは ../../../include/test.h のはずですが、なぜこれでコンパイルが通るのでしょうか? ちなみに「追加のインクルードディレクトリ」に何も指定しない状態では、includeファイルを開けないと出てコンパイルエラーとなります。 なのでこの設定が影響しているのだとは思いますが。