ヒープメモリ解放の問題とは?

このQ&Aのポイント
  • VCを始めたばかりで、メモリ等の事が良くわかりません。
  • Invalid Address specified to RtlValidateHeapやHEAP: Free Heap block modified at after it was freedのメモリエラーが出力されます。
  • delete pBufが処理されていないと思います。記述等に問題があるのでしょうか?
回答を見る
  • ベストアンサー

ヒープメモリの解放について

すみません教えてください。 VCを始めたばかりで、メモリ等の事が良くわかりません。 (2)で、Invalid Address specified to RtlValidateHeap( 340000, 344978 )やHEAP: Free Heap block 344970 modified at 344998 after it was freed のメモリエラーが出力されます。 調べてみると(1)で解放されていないのですが、delete pBufが処理されていないと思います。 記述等に問題があるのでしょうか? 調べてみると問題ないように思えるのですが・・・ ご存知の方教えてください。 <ソース> HANDLE hEventLog = NULL; EVENTLOGRECORD *pBuf = NULL; /* イベントログのオープン処理 */ : : : /* イベントログの最大数 */ bResult = GetNumberOfEventLogRecords(hEventLog, &EventNum); //最大サイズを取得 BufSize = 1; pBuf = new EVENTLOGRECORD; bResult = ::ReadEventLog(hEventLog,EVENTLOG_FORWARDS_READ | EVENTLOG_SEQUENTIAL_READ,0,pBuf,BufSize,&ReadBytes,&NextSize); if(!bResult && GetLastError() != ERROR_INSUFFICIENT_BUFFER) {  eMsg = "ファイルリードエラー2" ;  CloseEventLog(hEventLog);  delete pBuf;  return -1; } delete pBuf; --->(1)メモリが解放されない。 BufSize = NextSize; bResult = ::ReadEventLog(hEventLog,EVENTLOG_FORWARDS_READ | EVENTLOG_SEQUENTIAL_READ,0,pBuf,BufSize,&ReadBytes,&NextSize); if(!bResult && GetLastError() != ERROR_INSUFFICIENT_BUFFER){  eMsg = "ファイルリードエラー3";  CloseEventLog(hEventLog);  delete pBuf;  return -1;  } } delete pBuf; --->(2)ここでエラー

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

  • ベストアンサー
  • taka_tetsu
  • ベストアンサー率65% (1020/1553)
回答No.2

ちょっと順番が前後しますが、 >コンパイルしても定義されていない見たいだし、MSDNで調べてもLPEVENTLOGRECORDが無かったものですから・・ すみません。PEVENTLOGRECORDの間違いですね。 EVENTLOGRECORD*のことです。 という前提で、 >これはヒープメモリがオーバーしたため足りない60サイズを要求しているって意味ですよね? そうです。 >だとすると、記載してあった >char * pBuf2 = new char[NextSize]; >pBuf = (LPEVENTLOGRECORD)pBuf2; >で確保するのでしょうか? そうなります。 >また、なぜchar型でメモリ領域を作成し、 >EVENTLOGRECORD型でpBufにキャストするのでしょうか? >pBufはEVENTLOGRECORDですよね? new EVENTLOGRECORD; で確保可能な領域は、EVENTLOGRECORDのサイズを単位としてしか確保できませんよね。 charであれば、1バイト単位で必要なサイズ分を確保することが可能なのでこのような方法を取ります。

その他の回答 (1)

  • taka_tetsu
  • ベストアンサー率65% (1020/1553)
回答No.1

このエラーは、確保した領域を越えて書き込みが行われているときや、解放済みの領域に書き込みが行われた際に出るエラーです。 なんで、 >調べてみると(1)で解放されていないのですが、delete pBufが処理されていないと思います。 ではなく、 2回目のReadEventLogでpBufが指す領域が既に解放されている領域を渡しているため、ここに書き込まれてエラーになっています。 つまり、領域を確保してないですよってことです。 で、今回のエラーとは直接関係無いんですが、 1度目のReadEventLogで取得したNextSizeは、EVENTLOGRECORDのサイズより大きいことがあるので、 char * pBuf2 = new char[NextSize]; pBuf = (LPEVENTLOGRECORD)pBuf2; というように確保する必要があり、 delete[] pBuf2; と解放する必要があります。おそらくひっかかる個所だと思いますんで。

poposan
質問者

補足

ご回答 ありがとうございます。 間違ってコメントアウトして記入忘れしていたのですが、 : : delete pBuf; ---------------------ここから2回目のREADEVENTLOG BufSize = NextSize; pBuf = new EVENTLOGRECORD; <-- 記述を忘れていました。 bResult = ::ReadEventLog (hEventLog,EVENTLOG_FORWARDS_READ | EVENTLOG_SEQUENTIAL_READ,0,pBuf,BufSize,&ReadBytes,&NextSize); で、コンパイルしてみたところ、Heap block at 00344970 modified at 003449D8 past requested size of 60とでます。 これはヒープメモリがオーバーしたため足りない60サイズを要求しているって意味ですよね? だとすると、記載してあった char * pBuf2 = new char[NextSize]; pBuf = (LPEVENTLOGRECORD)pBuf2; で確保するのでしょうか? また、なぜchar型でメモリ領域を作成し、EVENTLOGRECORD型でpBufにキャストするのでしょうか? pBufはEVENTLOGRECORDですよね? 因みに(LPEVENTLOGRECORD)って(EVENTLOGRECORD)が正しいのですよね?(間違っていたらすみません。) コンパイルしても定義されていない見たいだし、MSDNで調べてもLPEVENTLOGRECORDが無かったものですから・・ たびたび聞いて申し訳ありません。

関連するQ&A

  • イベントログの読み込み 

    すみません。 教えてくださいませ。 早速ですが、Vc++でイベントログを取得するプログラムを作成しているのですが、うまくいきません。 [ソース] DWORD BufSize; DWORD ReadBytes; DWORD NextSize; DWORD EventNum; BOOL bResult; HANDLE hEventLog = NULL; HGLOBAL hDIB; try{ /* イベントログのオープン */ hEventLog = ::OpenEventLog(NULL, "Application"); if(hEventLog == NULL){ eMsg = "ファイルオープンエラー"; return -1; } /* イベントログの最大数 */ bResult = GetNumberOfEventLogRecords(hEventLog, &EventNum); for(;;){ //最大サイズを取得 BufSize = 1; hDIB = GlobalAlloc(GMEM_FIXED, BufSize); bResult = ::ReadEventLog(hEventLog,EVENTLOG_FORWARDS_READ | EVENTLOG_SEQUENTIAL_READ,0,hDIB,BufSize,&ReadBytes,&NextSize); if(!bResult && GetLastError() != ERROR_INSUFFICIENT_BUFFER) { eMsg = "ファイルリードエラー"; CloseEventLog(hEventLog); GlobalFree(hDIB); return -1; } GlobalFree(hDIB); hDIB = NULL; BufSize = NextSize; hDIB = ::GlobalAlloc(GMEM_FIXED, BufSize); bResult = ::ReadEventLog(hEventLog,EVENTLOG_FORWARDS_READ | EVENTLOG_SEQUENTIAL_READ,0,hDIB,BufSize,&ReadBytes,&NextSize); if(!bResult){ eMsg = "ファイルリードエラー"; CloseEventLog(hEventLog); GlobalFree(hDIB); return -1; } } }catch(CException* e){ if(hEventLog != NULL){ eMsg = (LPCTSTR)e; CloseEventLog(hEventLog); } } GlobalFree(hDIB); return 1; [内容] 正常にコンパイルはするのですが、実行後エラーが出力されます。"ファイルリードエラー"(エラー文) メモリの確保がうまくいっていないのでしょうか?

  • ReadEventLogについて

    教えてください。 ReadEventLogでイベントログ情報を取得したいのですが、わからない所があります。 ReadEventLogのpBufはEVENTLOGRECORD型なのです。ですが、メモリを確保するためGlobalAllocを使いたいのですが、HGLOBAL(Void)型なのでキャストしてもうまくいきません。 型を変える方法があるのでしょうか? あるのであれば教えてください。 [ソース一部] EVENTLOGRECORD *pBuf = NULL; HGLOBAL hDIB; hDIB = GlobalAlloc(GMEM_FIXED, BufSize); pBuf = (EVENTLOGRECORD)hDIB; //★ここでエラー bResult = ::ReadEventLog(hEventLog,EVENTLOG_FORWARDS_READ | EVENTLOG_SEQUENTIAL_READ,0,pBuf,BufSize,&ReadBytes,&NextSize);

  • 非同期のプロセス間通信(パイプ)で全データ受信する

    こんにちは。 非同期のプロセス間通信(パイプ)で詰まっています。 環境はWindowsで処理系はC++(Win32)です。 スレッドを用意して、 hPipe = ::CreateFile( L"\\\\.\\pipe\\pipename", GENERIC_WRITE | GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_FLAG_OVERLAPPED, NULL ) ; で作成し、OVERLAPPED構造体を // ZeroMemory( &so, sizeof( OVERLAPPED )) ; sOverlapped.hEvent = ::CreateEvent( NULL, FALSE, FALSE, NULL ) ; として、 const size_t bufsize = 16 ; BYTE     buffer[ uBufSize ] ; DWORD    dwNumberOfBytesRead ; bRet = ::ReadFile( hPipe, buffer, bufsize, &dwNumberOfBytesRead, &so ) ; で読み込みをしています。ReadFile関数はすぐ戻りbRetはFALSEで返ってくるため、GetLastErrorを調べて、 switch( ::GetLastError()) {   case ERROR_IO_PENDING :     bRet = ::GetOverlappedResult( hPipe, &so, &dwNumberOfBytesRead, FALSE ) ;     break ; } としてWaitForMultipleObjectsでsOverlapped.hEventがシグナル状態になったら取得したデータの処理をしています。 シグナル状態になるならないに関わらず、上記のReadFileとGetOverlappedResultはループでぐるぐる回しています。 上記の状態で短いデータならよかったのですが、上記のReadFileで読み込み最大サイズの16バイトを超えてしまとうと、 残りの部分のみしか取得できませんでした。 0123456789ABCDEFabcdefg というデータを受信しようとしたとき、後半のabcdefgだけしか取得できませんでした。 すべてのデータを正しく取得するにはどのようにしたらよいのでしょうか?

  • ディスクのreadよりwriteが速い?

    RHEL4.6にて RAID0+1 SAS 300GB 15000rpm × 3 × 2 で 900GBのアレイを作成しました。 bonnieなるベンチマークソフトで測定したところ以下のような結果となりました。 これってシーケンシャルreadよりwriteのほうが速いように見えるのですが、writeのほうが速いということはあるのでしょうか? Version 1.03b ------Sequential Output------ --Sequential Input- --Random- -Per Chr- --Block-- -Rewrite- -Per Chr- --Block-- --Seeks-- Machine Size K/sec %CP K/sec %CP K/sec %CP K/sec %CP K/sec %CP /sec %CP hostabcd 20000M 53326 96 245352 62 118227 34 59936 95 369497 57 539.3 1 ------Sequential Create------ --------Random Create-------- -Create-- --Read--- -Delete-- -Create-- --Read--- -Delete-- files /sec %CP /sec %CP /sec %CP /sec %CP /sec %CP /sec %CP 16 +++++ +++ +++++ +++ +++++ +++ +++++ +++ +++++ +++ +++++ +++ よろしくお願いいたします。

  • 多次元配列を動的に取る方法で悩んでいます。

    現在、以下のコードで三次元配列を動的に取る方法を作成しています。 { int i,j; char ***Regdata; LPVOID heapAdr; Regdata = (char ***)HeapAlloc(GetProcessHeap(),HEAP_NO_SERIALIZE,sizeof(char) * 1000); for(i=0;i<=1000;i++){ heapAdr = HeapAlloc(GetProcessHeap(), //ここでエラーが発生します。 HEAP_NO_SERIALIZE | HEAP_ZERO_MEMORY, sizeof(char) * 6); if(heapAdr != NULL) { Regdata[i] = (char **)heapAdr; for(j=0;j<=6;j++){ heapAdr = HeapAlloc(GetProcessHeap(), HEAP_NO_SERIALIZE | HEAP_ZERO_MEMORY, sizeof(char) * STRING_LENGTH); if(heapAdr != NULL) { Regdata[i][j] = (char *)heapAdr; } else { break; } } } else { break; } } } この方法だと、約40~50回ループした時点でHeapAlloc関数のところで 実行時エラーが発生してしまいます。 GetLastError関数を用いてエラーメッセージを取得したところ、 「No 998:メモリの場所に無効なアクセスがありました。」 というメッセージが返ってきました。 現状、どうしたらよいのかわからない状態です。 ご存知の方がいらっしゃれば、お教えいただきたいです。 以上、宜しくお願いします。

  • 圧縮クライアントのプログラム

    java eclipeを使って通信のプログラムを勉強しています。 参考にしている本は、TCP/IPソケットプログラミングjava編です。 本に書かれてるソースコードのとおりに入力したら、 Exception in thread "main" java.io.FileNotFoundException: test.txt (No such file or directory) at java.io.FileInputStream.open(Native Method) at java.io.FileInputStream.<init>(Unknown Source) at java.io.FileInputStream.<init>(Unknown Source) at socket_127.CompressClient.main(CompressClient.java:20) というエラーが出ました。 このエラーを調べると、 「指定されたパス名で示されるファイルが開けなかったことを通知します。」とかかれていました。このプログラムが入っているフォルダの中にtest.txtというテキストファイルを作成して同じフォルダに入れてあります。 このプログラムの引数は、 <Server> IPアドレス <Port>  110 <File> test.txt としました。 このエラーをとる方法を教えていただけないでしょうか? 下にソースコードを載せますので、解決方法をお願いします。 package socket_127; import java.net.*; // for Socket import java.io.*; // for IOException and [File]Input/OutputStream public class CompressClient { public static final int BUFSIZE = 256; // Size of read buffer public static void main(String[] args) throws IOException { if (args.length != 3) throw new IllegalArgumentException("Parameter(s): <Server> <Port> <File>"); String server = args[0]; int port = Integer.parseInt(args[1]); String filename = args[2]; FileInputStream fileIn = new FileInputStream(filename); FileOutputStream fileOut = new FileOutputStream(filename + ".gz"); Socket sock = new Socket(server, port); sendBytes(sock, fileIn); InputStream sockIn = sock.getInputStream(); int bytesRead; byte[] buffer = new byte[BUFSIZE]; while ((bytesRead = sockIn.read(buffer)) != -1) { fileOut.write(buffer, 0, bytesRead); System.out.print("R"); } System.out.println(); sock.close(); fileIn.close(); fileOut.close(); } private static void sendBytes(Socket sock, InputStream fileIn) throws IOException { OutputStream sockOut = sock.getOutputStream(); int bytesRead; byte[] buffer = new byte[BUFSIZE]; while ((bytesRead = fileIn.read(buffer)) != -1) { sockOut.write(buffer, 0, bytesRead); System.out.print("W"); } sock.shutdownOutput(); } }

  • デスクトップパソコンの調子が悪くなりました。

    先月より仕事用のwindows7(professional 64bit)パソコンの調子が悪くなってきました。症状は以下の通りです。 ・「A disk read error occurred…」の表示があり、Ctrl+Alt+Deleteを押しても再起動できず。強制的に電源を落とすも、次回起動時に普通に起動する。 ・使用中に重くなり、5~10分ほどフリーズする。その後元に戻る。 メモリはwindowsの診断機能で問題ないとの結果で、HDDは3か月前に交換してwindowをインストールしたばかりです。 似たような経験をされた方がいれば解決策を教えてください。よろしくお願いします。

  • ロック解除時に出るえらーメッセージについて

    スクリーンセーバをかけてロックを解除するときに[Ctrl]+[Alt]+[Delete]キーを押した後に、次のエラーが表示されます。 ************************************************************ 【タイトル】 コンピュータのロック:winlogon.exe - アプリケーションエラー - 【内容】 "0x3a69bd85"の命令が"0x00d1402"のメモリを参照しました。メモリが"read"になることはできませんでした。 プログラムを終了するには[OK]をクリックしてください プログラムをデバックするには[キャンセル]をクリックしてください ************************************************************ [OK]をクリックしても[キャンセル]をクリックしても、ウインドウズではない青い画面が出て、[Hard・・・unnown]??的なメッセージが非画面左上部に出て、どのキーを押しても反応がないため、電源キーを5秒程度押したままにして、パソコンの電源を切って再起動しております。 何が原因なのでしょうか? 1日に1回程度このような症状が現れます。 Windows XP Pro 2002 SP2を使用しております。 どなたかご存知の方おりましたら、解決方法を教えてください。

  • ソフトのプログラムが読みだし可能領域を外れてエラーが出てしまいます(T_T)

    ビデオ編集ソフトPremiere Pro CS4を使っているのですが… 最近になってレンダリング作業というのを実行している時、 「"0x00accacc"の命令が"0x00000014"のメモリを参照しました。メモリが"read"になることはできませんでした。 」 というエラーが出て、ソフトが強制終了になってしまう事が頻繁に出るようになりました。 原因としては起動中のプログラムが、読みだし可能領域をはずれて READ した時に出るエラーらしいです。 しかし、以前は同じ作業をしていてもそのような事はありませんでした。 ソフトの最インストールなどもしてみましたが変化なしです。 今回の因果関係は分かりませんが、 ちょっと前にシステムドライブのパーテンションを変更したりもしました。 システムドライブは500GBHDDに対して270GB割り当てて、 残り200GB程は別のボリュームに割り当ててます。 私の環境は… ●WindowsXP SP3 ●Core2 Quad ●メモリ=3.24GB (実際には2G+2G=4GB) ●仮想メモリ設定は初期サイズ、最大サイズ共に4000MB ●Premiere Pro CS4 ver.4.2.1 何か?システム上で考えられる手立ては無いものでしょうか?? どなたかご教授お願いいたします。 また、ついでにHDDの管理について… HDDの「パーテーションをアクティブにしてマーク」 とはどういった意味でしょうか? ついでにお分かりになる方おられましたら有難いです。 m(_ _)m

  • ファイルのアップローダーを動作させたい。

    ファイルをサーバーへ格納するプログラムを検索して作成しました。 見よう見まねなのでおかしい部分があるかもしれません。 entry.cgi #!/perl/bin/perl my $buffer; my $query = CGI->new; my $fh = $query->upload('file') or die(qq(Invalid file handle returned.)); # Get $fh my $file = $query->param('file'); my $file_name = ($file =~ /([^\\\/:]+)$/) ? $1 : 'uploaded.bin'; open(OUT, ">$file_name") or die(qq(Can't open "$file_name".)); binmode OUT; while (read($fh, $buffer, 1024)) { # Read from $fh insted of $file print OUT $buffer; } close OUT; sample.html <HTM><BODY> <FORM METHOD="POST" ENCTYPE="multipart/form-data" ACTION="./entry.cgi"> <TABLE BORDER="1"> <TR><TD ><B>CSVファイル</B></TD> <TD ><INPUT TYPE="FILE" NAME="filename"></TD></TR> <TR></TR> </TABLE> <BR> <BR> <INPUT TYPE="SUBMIT" NAME="GO" VALUE=" 登録の実行 "> </FORM> </BODY></HTML> 上記のプログラムを実行すると 「CGIWrap Error: Script Execution Failed」と表示されてしまいます。 500のサーバーエラーと同じと調べてわかったのですが、どこがどうおかしいのか?わかりません。 perlの記述が今まで自分が使用していたものと勝手が違うので分からない状態です。 アドバイスもらえると幸いです。

専門家に質問してみよう