
メモリリークについて教えてください。
最近VC++を勉強中なのですが、メモリリークというものを知り、_CrtDumpMemoryLeaks()をしたところ、以下のコメントが出力されました。
[コメント]
Detected memory leaks!
Dumping objects ->
strcore.cpp(118) : {71} normal block at 0x00344978, 20 bytes long.
Data: < cmd.> 01 00 00 00 07 00 00 00 07 00 00 00 63 6D 64 2E
{48} client block at 0x003428E8, subtype 0, 64 bytes long.
a CDynLinkLibrary object at $003428E8, 64 bytes long
{43} client block at 0x00342720, subtype 0, 64 bytes long.
a CDynLinkLibrary object at $00342720, 64 bytes long
{41} client block at 0x003425D0, subtype 0, 64 bytes long.
a CDynLinkLibrary object at $003425D0, 64 bytes long
Object dump complete.
スレッド 0x584 終了、終了コード 0 (0x0)。
上記のコメントから、メモリリークを起こしていることはわかりました。ただ、strcore.cppというクラスは作成していないのですが、エラーが出ます。
多分他の関数から呼ばれているクラスだと思うため、クラス等をコメントアウトして調べたのですが、エラーがまだ出力されます。
(Data: < cmd.> 01 00 00 00 07 00 00 00 07 00 00 00 63 6D 64 2Eここは自作クラス上の問題だと思います。)
newとかの解放はしているのですが、他にメモリリークをする原因ってあるのでしょうか?
No.4
- 回答日時:
>PCか、vc++か、記述に問題があるのか・・・
記述というか確認方法ですかね。
_CrtDumpMemoryLeaks()を呼ぶタイミングが早すぎます。ローカル変数のデストラクタが呼ばれていません。
中括弧で処理を囲って、その前後でメモリリーク調査の関数を呼んでください。
もしくは調査対象の処理を別関数にするか。
void CMy2Dlg::OnOK()
{
// TODO: この位置にその他の検証用のコードを追加してください
_CrtSetBreakAlloc(71);
{ //追加
PROCESS_INFORMATION pro_id;
STARTUPINFO str_inf;
::ZeroMemory(&str_inf, sizeof(str_inf));
str_inf.cb = sizeof(str_inf);
str_inf.dwFlags = STARTF_USESHOWWINDOW;
str_inf.wShowWindow = SW_SHOW;
CString mstrCmdLine;
mstrCmdLine = "cmd.exe";
char *cl = new char[mstrCmdLine.GetLength() + 2];
strcpy(cl,mstrCmdLine);
CreateProcess(NULL,cl,NULL,NULL,FALSE,0,NULL,NULL,&str_inf,&pro_id);
delete[] cl;
CDialog::OnOK();
} //追加
_CrtDumpMemoryLeaks();
}
この回答への補足
いつもありがとうございます。
[ソース]
void CMy2Dlg::OnOK()
{
_CrtSetBreakAlloc(71);
{
// TODO: この位置にその他の検証用のコードを追加してください。
PROCESS_INFORMATION pro_id;
STARTUPINFO str_inf;
::ZeroMemory(&str_inf,sizeof(str_inf));
str_inf.cb = sizeof(str_inf);
str_inf.dwFlags = STARTF_USESHOWWINDOW;
str_inf.wShowWindow = SW_SHOW;
CString mstrCmdLine;
mstrCmdLine = "cmd.exe";
char *cl = new char[mstrCmdLine.GetLength() + 2];
strcpy(cl,mstrCmdLine);
CreateProcess(NULL,cl,NULL,NULL,FALSE,0,NULL,NULL,&str_inf,&pro_id);
delete[] cl;
CloseHandle(pro_id.hProcess);
CDialog::OnOK();
}
_CrtDumpMemoryLeaks();
}
以上のように記述したら、以下のような結果になりました。
umping objects ->
{48} client block at 0x003428E8, subtype 0, 64 bytes long.
a CDynLinkLibrary object at $003428E8, 64 bytes long
{43} client block at 0x00342720, subtype 0, 64 bytes long.
a CDynLinkLibrary object at $00342720, 64 bytes long
{41} client block at 0x003425D0, subtype 0, 64 bytes long.
a CDynLinkLibrary object at $003425D0, 64 bytes long
Object dump complete.
スレッド 0x790 終了、終了コード 0 (0x0)。
プログラム 'D:\work\1.docomo\作業\20050114 ファイルコピー\test\2\Debug\2.exe' はコード 0 (0x0) で終了しました。
一様CString系のメモリリークはなくなりました。
他のは調べていますが、よくわかりません。
問題ないようにも思えますが・・・
No.3
- 回答日時:
-----
PROCESS_INFORMATION pro_id;
STARTUPINFO str_inf;
::ZeroMemory(&str_inf, sizeof(str_inf));
str_inf.cb = sizeof(str_inf);
str_inf.dwFlags = STARTF_USESHOWWINDOW;
str_inf.wShowWindow = SW_SHOW;
CString mstrCmdLine;
mstrCmdLine = "cmd.exe";
char *cl = new char[mstrCmdLine.GetLength() + 2];
strcpy(cl,mstrCmdLine);
CreateProcess(NULL,cl,NULL,NULL,FALSE,0,NULL,NULL,&str_inf,&pro_id);
delete[] cl;
-----
というコードを実行してみましたが、メモリリークは発生しませんでした。
ですので、原因はまだ明かされていないコードのどこかにあるのではないかと思います。
_CrtDumpMemoryLeaksにおいてメモリリークが検出された場合、一番最後に表示されたメモリリークに問題がある場合が多いです。
下から順番に解決していきましょう。
{41} client block at 0x003425D0, subtype 0, 64 bytes long.
a CDynLinkLibrary object at $003425D0, 64 bytes long
最初に解析するのはこれです。
このメモリリークの原因はもう解決しましたか?
●このメモリリークの原因探しに難航している場合
プログラムの先頭の方に
_CrtSetBreakAlloc(41);
というコードを追加し、デバッグモードで実行してみましょう。
うまく行けば、メモリリークを起こしているオブジェクトを生成しているところで停止してくれます。
停止したら、そのオブジェクトが本当に解放されているのか確認してみて下さい。
●残りはもうstrcore.cppで発生しているメモリリークだけの場合
strcore.cpp(118) : {71} normal block at 0x00344978, 20 bytes long.
Data: < cmd.> 01 00 00 00 07 00 00 00 07 00 00 00 63 6D 64 2E
となっていますので、
プログラムの先頭の方に
_CrtSetBreakAlloc(71);
というコードを追加し、デバッグモードで実行してみましょう。
うまく行けば、メモリリークを起こしているオブジェクトを生成しているところで停止してくれます。
停止したら、そのオブジェクトが本当に解放されているのか確認してみて下さい。
ただしどちらの方法も起動するたびに{}の中の数字が変わるような状況では役に立ちません。ご注意下さい。
この回答への補足
ありがとうございます。
大変勉強になります。
まず、新規にVC6++を立ち上げ(MFC(exe)→ダイアログ)、以下のソースを入力したところ同じメモリリークになりました。(提供されたソースをコピーしました)
[ソース]
void CMy2Dlg::OnOK()
{
// TODO: この位置にその他の検証用のコードを追加してください
_CrtSetBreakAlloc(71);
PROCESS_INFORMATION pro_id;
STARTUPINFO str_inf;
::ZeroMemory(&str_inf, sizeof(str_inf));
str_inf.cb = sizeof(str_inf);
str_inf.dwFlags = STARTF_USESHOWWINDOW;
str_inf.wShowWindow = SW_SHOW;
CString mstrCmdLine;
mstrCmdLine = "cmd.exe";
char *cl = new char[mstrCmdLine.GetLength() + 2];
strcpy(cl,mstrCmdLine);
CreateProcess(NULL,cl,NULL,NULL,FALSE,0,NULL,NULL,&str_inf,&pro_id);
delete[] cl;
CDialog::OnOK();
_CrtDumpMemoryLeaks();
}
ですが、
Detected memory leaks!
Dumping objects ->
strcore.cpp(118) : {71} normal block at 0x00344908, 20 bytes long.
Data: < cmd.> 01 00 00 00 07 00 00 00 07 00 00 00 63 6D 64 2E
{48} client block at 0x003428E8, subtype 0, 64 bytes long.
a CDynLinkLibrary object at $003428E8, 64 bytes long
{43} client block at 0x00342720, subtype 0, 64 bytes long.
a CDynLinkLibrary object at $00342720, 64 bytes long
{41} client block at 0x003425D0, subtype 0, 64 bytes long.
a CDynLinkLibrary object at $003425D0, 64 bytes long
Object dump complete.
スレッド 0x6C4 終了、終了コード 0 (0x0)。
の同じ結果が返ってきます。
PCか、vc++か、記述に問題があるのか・・・
因みに、教えていただきました_CrtSetBreakAllocですが41、43、48でブレークはしませんでした。
71でブレークし見ると、
---------------------------
/* break into debugger at specific memory allocation */
if (lRequest == _crtBreakAlloc)
_CrtDbgBreak(); < ---- ここでとまっている。
---------------------------
そのままF10(Nextコンパイル)で見ていくと、
char *cl = new char[mstrCmdLine.GetLength() + 2];
に戻ってきます。
何か設定していないことがあるのか??
No.2
- 回答日時:
ヘルプより:
>lpCommandLine
>実行するべきコマンドラインを保持している、NULL で終わる文字列へのポインタを指定します。
>システムはこのコマンドラインの最後に NULL を追加し、必要に応じて文字列を切り捨て、
>実際にどのファイルを使うのか指定します。
なんで、
>char *cl = new char[mstrCmdLine.GetLength() + 1];
足りてません。1ではなく2足してください。
>例 LPTSTR mstrCmdLine;
>mstrCmdLine = "cmd.exe";
これってキャストしないでコンパイル通りますか?
この回答への補足
たびたびご回答ありがとうございます。
OS windows2000
visual c++ 6.0 を使用しています。
■1
>char *cl = new char[mstrCmdLine.GetLength() + 2];
にしましたが、以前と変わらずエラーが出ました。
もっと調べないとだめですね(^^;
納得いかないですね。
■2
>例 LPTSTR mstrCmdLine;
>mstrCmdLine = "cmd.exe";
>これってキャストしないでコンパイル通りますか?
class xxx : CObject
private:
LPTSTR mstrCmdLine;
:
:
}
int xxx::xxxx(){
mstrCmdLine = "cmd.exe";
:
:
:
}
でやったらコンパイル通りました。
今考えると可笑しいですね。?(^^;?
No.1
- 回答日時:
>ただ、strcore.cppというクラスは作成していないのですが、エラーが出ます。
.cppって位だからソースでしょ(^^;;;
で、(118)が行番号。
MFCのソースはインストールしてますか?
VC++6.0SP6だと、該当行はCString::AllocBuffer()でした。
>newとかの解放はしているのですが、他にメモリリークをする原因ってあるのでしょうか?
ちゃんと解放していないとか。
こんなソースだとリークします。
CString pstr* = new CString[2];
delete pstr;
あとは、MFC等のフレームワークを使っているのであれば、その内部。
メモリリークとは、何度も確保されても解放されずに使用量が増えていくのがまずいのであって、該当個所では1度だけ確保して終了時まで保持しておくという使い方であれば、まずくはありません。(気持ち悪い気もしますが)
この回答への補足
ありがとうございます。
原因の個所がわかりました。
[ソース] 一部抜粋
CString mstrCmdLine;
mstrCmdLine = "cmd.exe";
char *cl = new char[mstrCmdLine.GetLength() + 1];
strcpy(cl,mstrCmdLine);
nResult = CreateProcess(NULL,cl,NULL,NULL,FALSE,0,NULL,NULL,&str_inf,&pro_id);
delete[] cl;
CStringからLPTSTR型に変換をすると、CreateProcessでエラーが発生します。(cl)
直接clの部分を"cmd.exe"に直接記述するとメモリリークは起こさないみたいなので、char* への変換が間違っているのですか?
だとするとCStringからchar*への変換は良くないのでしょうか?
直接変数を LPTSTR型で領域を確保したほうがよろしいのですか?
例 LPTSTR mstrCmdLine;
mstrCmdLine = "cmd.exe";
nResult = CreateProcess(NULL,mstrCmdLine,NULL,NULL,FALSE,0,NULL,NULL,&str_inf,&pro_id);
お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!
似たような質問が見つかりました
- その他(プログラミング・Web制作) micropython コードについて 2 2023/06/14 13:13
- その他(プログラミング・Web制作) micropythonコード 修正 1 2023/06/13 17:22
- Visual Basic(VBA) EXCEL VBAにて動的にCheckBOXを複数作成し、同BOXにイベントを追加したい 1 2023/03/16 07:05
- Visual Basic(VBA) 別シートから年齢別の件数をカウントしたいの続き 5 2023/01/24 00:16
- 英語 Please let me know how you are getting( ). ①over ② 3 2023/01/31 12:15
- 英語 この英文の意味を教えてください 3 2023/07/07 20:36
- Visual Basic(VBA) excel vbaでvlooupの変数がわかりません。 7 2022/05/30 09:35
- Visual Basic(VBA) いつもお世話になっております、VBAで教えて頂きたいのですが 2 2022/05/05 22:20
- Visual Basic(VBA) VBA 請求書自動作成 3 2022/04/24 01:58
- Visual Basic(VBA) 前回ご教授いただいたコードに覚えたてのループ処理で品名りんごAから順に20回for nextでループ 7 2023/01/13 22:01
このQ&Aを見た人はこんなQ&Aも見ています
-
Detected memory leaks!
C言語・C++・C#
-
CStringからchar*への型変換について教えてください。
C言語・C++・C#
-
CString から LPCTSTRの型に変換
C言語・C++・C#
-
-
4
VC++ オリジナルDLLを使用するとアプリを終了させる時にメモリリークする
C言語・C++・C#
-
5
画面を強制的に再描画させる方法
C言語・C++・C#
-
6
Visual Studioのメモリリークについて
C言語・C++・C#
-
7
エディットコントロールでEnter押した時の動作
C言語・C++・C#
-
8
C ファイル出力で、フォルダがない場合でも作成する方法
C言語・C++・C#
-
9
DWORDの実際の型は何でしょうか
C言語・C++・C#
-
10
_tcscpy_s(wcscpy_s)の第二引数って
C言語・C++・C#
-
11
Debug Assertion Failed?
C言語・C++・C#
-
12
UpdateData( FALSE); による文字列データの表示更新(VC++6.0)
C言語・C++・C#
-
13
charからLPTSTRへの変換方法
C言語・C++・C#
-
14
CStringの文字列検索&抜き出しについて
C言語・C++・C#
-
15
ボタンの表示の色、フォントを変更したい
C言語・C++・C#
-
16
CStringのFindで文字列検索を行いたいのですが
C言語・C++・C#
-
17
ヒープメモリの解放について
C言語・C++・C#
-
18
#include <Windows.h>というヘッダファイルについて
C言語・C++・C#
-
19
VC++ で.bat起動
C言語・C++・C#
-
20
MFC ダイアログ上のID取得について
C言語・C++・C#
関連するカテゴリからQ&Aを探す
おすすめ情報
このQ&Aを見た人がよく見るQ&A
デイリーランキングこのカテゴリの人気デイリーQ&Aランキング
-
大量のデータを読み込んで表示...
-
visual studio 2022でのC#プロ...
-
Notepad++の関数リスト表示でC...
-
C言語について。
-
DNCL(共テ用プログラミング言語...
-
パソコン
-
gccを行ってもexeファイルが生...
-
pythonの質問です。
-
VisualStudio2022でC言語プログ...
-
C言語の関数のextern宣言
-
C#でTreeViewのCheckBoxのサイ...
-
バッチファイルで以下のような...
-
ArduinoでMouse関数を使用して...
-
c言語でイベントフラグを使った...
-
【C言語】全角文字の配列を、全...
-
Windows Formアプリからコンソ...
-
プログラマー達は何故、プログ...
-
最初に聞かれたこと
-
DNCL(共テ用プログラミング言語...
-
C# で 数式文字列処理を処理す...
マンスリーランキングこのカテゴリの人気マンスリーQ&Aランキング
-
visual studio 2022でのC#プロ...
-
Windows Formアプリからコンソ...
-
大量のデータを読み込んで表示...
-
C言語の関数のextern宣言
-
C#でログファイルにファイルパ...
-
【C言語】全角文字の配列を、全...
-
略語の読み方について
-
プログラマー達は何故、プログ...
-
C#でTreeViewのCheckBoxのサイ...
-
gccを行ってもexeファイルが生...
-
c言語でイベントフラグを使った...
-
VisualStudio2022でC言語プログ...
-
Python、プログラミングについ...
-
C言語 列挙型(enum型)変数について
-
VisualStudioでC++クラスを追加...
-
int16_t の _t は何?
-
Notepad++の関数リスト表示の変...
-
コンソールアプリを作成するの...
-
逆コンパイルと逆アセンブルの...
-
MACで動く実行ファイルをWindow...
おすすめ情報