質問

4 年前の VC++ 6.0 プログラムに機能拡張を追加しようとしています。デバッグ ビルドはコマンド ラインから実行されますが、デバッガーでは実行されません。printf() 内でアクセス違反が発生してクラッシュします。printf をスキップすると、malloc() (fopen() 内から呼び出される) でクラッシュし、スキップできません。

つまり、デバッガーで実行することができず、何が起こっているかを確認するには古い printf ステートメントに依存する必要があります。これにより明らかに作業が大幅に困難になります。

VC++ デバッガーで実行すると printf() と malloc() が失敗する理由はありますか?私はこんな低レベルなものは苦手です!

アクセス違反後のコールスタックは次のとおりです。

_heap_alloc_dbg(unsigned int 24, int 2, const char * 0x0046b3d8 `string', int 225) line 394 + 8 bytes
_nh_malloc_dbg(unsigned int 24, int 0, int 2, const char * 0x0046b3d8 `string', int 225) line 242 + 21 bytes
_malloc_dbg(unsigned int 24, int 2, const char * 0x0046b3d8 `string', int 225) line 163 + 27 bytes
_lock(int 2) line 225 + 19 bytes
_getstream() line 55 + 7 bytes
_fsopen(const char * 0x00468000 `string', const char * 0x00466280 `string', int 64) line 61 + 5 bytes
fopen(const char * 0x00468000 `string', const char * 0x00466280 `string') line 104 + 15 bytes
open_new_log(const char * 0x00468000 `string') line 66 + 14 bytes
log_open(const char * 0x00468000 `string', int 0) line 106 + 9 bytes
Xlog_open(const char * 0x00468000 `string', int 0) line 51 + 13 bytes
service_start(unsigned long 1, char * * 0x009a0e50) line 3152 + 12 bytes
service_init2(char * 0x00471fcc char * NTPROGRAM, char * 0x004723c4 char * NTSERVICE, char * 0x00466540 `string', unsigned long 1, char * * 0x009a0e50) line 508 + 13 bytes
service_init(char * 0x00471fcc char * NTPROGRAM, char * 0x004723c4 char * NTSERVICE, unsigned long 2, char * * 0x009a0e50) line 548
main(unsigned long 2, char * * 0x009a0e50) line 3131
mainCRTStartup() line 206 + 25 bytes
KERNEL32! 7c817067()

失敗する操作までのデバッグ逆アセンブリは次のとおりです。

0041EA7E   jmp         _heap_alloc_dbg+2B3h (0041eb23)
0041EA83   mov         edx,dword ptr [_lTotalAlloc (004b4294)]
0041EA89   add         edx,dword ptr [nSize]
0041EA8C   mov         dword ptr [_lTotalAlloc (004b4294)],edx
0041EA92   mov         eax,[_lCurAlloc (004b429c)]
0041EA97   add         eax,dword ptr [nSize]
0041EA9A   mov         [_lCurAlloc (004b429c)],eax
0041EA9F   mov         ecx,dword ptr [_lCurAlloc (004b429c)]
0041EAA5   cmp         ecx,dword ptr [_lMaxAlloc (004b42a0)]
0041EAAB   jbe         _heap_alloc_dbg+249h (0041eab9)
0041EAAD   mov         edx,dword ptr [_lCurAlloc (004b429c)]
0041EAB3   mov         dword ptr [_lMaxAlloc (004b42a0)],edx
0041EAB9   cmp         dword ptr [_pFirstBlock (004b4298)],0
0041EAC0   je          _heap_alloc_dbg+25Fh (0041eacf)
0041EAC2   mov         eax,[_pFirstBlock (004b4298)]
0041EAC7   mov         ecx,dword ptr [pHead]
0041EACA   mov         dword ptr [eax+4],ecx

fopen() を呼び出して malloc() で失敗するソースは次のとおりです。

FILE *open_new_log( const char *logfile )
{
    FILE *fp;
    int retry = 0;

    while( ( fp = fopen( logfile, "w" ) ) == NULL && ++retry < 300 )
        Sleep( 1000 );

    return( fp );
}

私が受け取るエラーは

Unhandled exception inPISCOOP.exe: 0xC00000005: Access Violation

よろしくお願いします。

--- アリステア。

役に立ちましたか?

解決

あなたは有効にするために _CrtSetDbgFlag() に使用することができます便利なヒープのデバッグ手法の束。 CRTのデバッグ機能が利用できるをhref="http://msdn.microsoft.com/en-us/library/1666sb98(VS.71).aspx" rel="nofollow noreferrer">他の

他のヒント

デバッガから実行すると、

、異なるヒープが使用されます。これは、のデバッグヒープのと呼ばれています。これは、デバッガの外で使用するヒープは異なる振る舞いを持っており、あなたはこのような問題をキャッチ助けることがあります。

Win32の「デバッグヒープは」VC ++「デバッグヒープ」とは区別されることに注意してください。両方がしかし、多かれ少なかれ同じことを行うことを意図しています。アプリを実行したときの挙動の違いを説明し、この記事のnoreferrer">

最も簡単なアプローチは (アプリケーションがメモリを過度に使用していないことを条件として)、全ページ ヒープ チェックを有効にすることです (これにより、割り当てが提供されるメモリ ページの後にいわゆるガード ページが配置され、その結果、正確なメモリ ページの位置が特定されます)破損が発生するコード内の場所に配置してください)。

あなたが持っていることを考えると、 Windows デバッグ ツール 便利です。次の gflags コマンドを実行して、フル ページ ヒープを構成します。

gflags[.exe] /p /enable yourapp.exe /full

実行可能ファイル名を指定する必要があることに注意してください 一人で (すなわち、パスプレフィックスなし!)
次に、デバッガーで実行するだけです。ヒープを破壊しようとする最初の試みで中断されます。ここでの違いは、ヒープ破損のほとんどは、(おそらく) 有効なヒープ操作が有効になったときに後で現れる遅延欠陥であることです。

以下にも注意してください:

gflags[.exe] /p /enable yourapp.exe /full /backwards

割り当ての前にガード ページが追加で配置されます。

/p スイッチのみを指定して実行すると、現在有効なヒープ ページ オプションが表示されます。

あなたはヒープ破損のバグを有することができます。 open_new_log()が呼び出される前に、あなたのアプリケーションは、ヒープが破損している可能性があります。

jmattias が正しいのではないかと思います。問題の根本原因は、クラッシュしている場所とは別の場所にある可能性があります。

ヒープの破損はさまざまな原因で発生する可能性があります。

  • 割り当てられたメモリ ブロックの終わり (または始まり) を超えて書き込むこと。
  • ポインターを 2 回解放するか、割り当てられなかったポインターを解放します。
  • プログラムをマルチスレッド化し、シングルスレッド (スレッドセーフではない) RTL とリンクします。
  • あるヒープからメモリを割り当て、別のヒープでメモリを解放します。
  • などなど、

Visual C++ を使用しているため、デバッグ ヒープの _CrtSetDbgFlag() 機能を使用してエラー チェックを有効にすることができます。malloc または free を呼び出すたびにヒープの整合性をチェックするように設定できます。実行は非常に遅くなりますが、バグの場所を正確に特定できるはずです。

コンパイラのドキュメントで _CrtSetDbgFlag を検索します。

私は、アプリケーションの残りの部分よりもC ++ランタイムの異なるバージョンでコンパイルされたDLLがあることは疑いを持っています。これは、多くの場合、違反「/ 『書かれた』アドレスXXXのメモリを 『読み取り』することができませんでした」になります。

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top