例外の言及
FILE* __cdecl _getstream
私は電話をかけfopen
ていますが、クラッシュし続けています。
AfxMessageBox("getting here 1");
FILE* filePtr = fopen(fileName, "rb");
AfxMessageBox("getting here 2");
どういうわけか、2 番目のメッセージ ボックスに到達しません。興味深いことに、デバッグ モードにすると、アプリは完全に機能します。なんで?
メモリの破損だと思います。Windows (__cdecl を使用していると思われます) では、Windows Debugging Tools に付属の gflags ユーティリティがあります。これにより、各ヒープ割り当てに独自のページを持たせることができます。これにより、問題が発生した時点でメモリ オーバーランと二重解放を即座にキャッチできます。
私は自分のブログに手順を書きました:
この種のバグを見つけるためのヒントは他にもあります。
これはかなりあいまいなので、これが多くの人に影響を与えるとは思えませんが、次のように FILE* を取得した場合:
HANDLE hMyFile = CreateFile(...);
FILE* pFile = _fdopen( _open_osfhandle((long)hMyFile, <flags>), "rb" );
CloseHandle(hMyFile);
次に、開いたファイルごとにストリームをリークします。_open_osfhandle と _fdopen を実行した後、pFile で fclose() を呼び出してハンドルを閉じる必要があります。CloseHandle は、fdopen がハンドルに関連付けるクラフトを解放するほどスマートではないようですが、fclose は、FILE* 関連のクラフトとともにハンドルを閉じるほどスマートです。
私が取り組んでいたアプリがこれを行ったのは、特定の API が HANDLE を通過し、API の特定の実装者が FILE* を必要としたため、実装者は _fdopen/_open_osfhandle を実行して FILE* を取得したためです。ただし、これは、呼び出し元の CloseHandle 呼び出しが HANDLE を完全に閉じるには不十分であることを意味していました。修正は、着信 HANDLE を最初に複製することでした。その後、FILE* コードは、呼び出し元の HANDLE を壊すことなく、FILE* を適切に fclose() できました。
壊れたプログラムの例:
#include "stdafx.h"
#include <Windows.h>
#include <io.h>
#include <assert.h>
#include <fcntl.h>
int _tmain(int argc, _TCHAR* argv[])
{
for(int x = 0;x < 1024; x++)
{
HANDLE hFile = CreateFile(L"c:\\temp\\rawdata.txt",GENERIC_READ,FILE_SHARE_READ,NULL,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,NULL);
FILE* pFile = _fdopen( _open_osfhandle((long)hFile, _O_RDONLY | _O_BINARY), "rb" );
assert(pFile); // this assert will go off at x=509, because _getstream() only has 512 streams, and 3 are reserved for stdin/stdout/stderr
CloseHandle(hFile);
}
return 0;
}
プログラムのその部分に問題はないと思います。最も可能性の高いシナリオは、コードの早い段階である種のメモリ破損が発生し、それがたまたま発生する場所であるということです。
プログラムの残りの部分 (その部分の後) をデバッグ モードで実行してみましたか? 何らかのメモリ破損である場合、デバッグ モード アロケータは、破損したメモリ領域の割り当てを解除するときにそれをキャッチする必要があります。もちろん、完全なデバッグ メモリ アロケータを備えたコンパイラを使用していると仮定します。
fileName に何か問題があると思います (末尾にゼロがありますか?)
fopen行をコメントアウトして、何が起こるか見てみましょう。