ようこそ ゲスト さん、新規登録(無料)して気になる疑問を解決しませんか?

質問

質問者:yuki7091 【VC++6.0(MFC)】MessageBoxを使わず、MessageBoxと同機能を表現するには?
困り度:
  • すぐに回答を!
いつも大変お世話になっております。
VC++初心者です。

現在、先人のつくったソースを見直しています。
ある条件になるとエラーを知らせるMessageBoxを出力するのですが、
デバグモードでMessageBoxが使われれている全ての箇所に
ブレイクポイントをおいても、それらのブレイクポイントに引っかかって
くれません。

そうなると、MessageBox以外の命令でMessageBoxと同様のことを
しているコードがあると思っているのですが、そういう機能の命令
はどのようなものがあるのでしょうか。

お手数ですが、よろしくお願いします。
質問投稿日時:09/10/16 07:18
質問番号:5370913
最新から表示回答順に表示

回答

 

回答者:noname#96502 まず何度かエラーメッセージが表示されているみたいなので、再現性があると思うのですが、再現手順は確立されているんでしょうか?
確立されているのなら、デバッグしながらその手順を行いプログラムを1行ずつ実行させれば良いと思うのですが。
確立されていないなら、確立する努力をするのが一番の近道だと思います。(コードの量と再現率によりますが)
それでも無理なら動的解析ツールを使った方が良いかも知れません。

以下はつぶやき。
MFCを使っているなら、メモリーリークはそれ程気にしなくても良いかも。MFC自体がリークしてるので。。。
それから動的なメモリ確保のメリットってどれくらいあるのでしょうか。。。
組込みの開発をしていて、ファイルの書き込み回数の制限があった時に圧縮をするときには圧縮後のサイズが事前に分からないので動的にメモリを確保しましたが、それ以外で動的にメモリを確保するメリットがあまり思い浮かびません。
PCアプリなら単純にファイルに書き込めば良いですし。。。
遠い記憶ですが、データサイズが事前に予測できないデータをファイルに書き込んでも、書き込んだデータは実はメモリ上に保持されていてファイルストリームを使って引き回しても処理速度が落ちなかった経験がありました。。。
種類:アドバイス
どんな人:一般人
自信:参考意見
回答日時:09/10/17 20:02
回答番号:No.9
この回答への補足この回答に補足をつける(質問者のみ)
この回答へのお礼この回答にお礼をつける(質問者のみ)

回答

 

回答者:hiro_knigh ちなみに、以前に貴方が以下で質問された件について
http://oshiete1.goo.ne.jp/qa5198719.html

>>オブジェクトのポインタを保持する変数に上書きでnewしてないか?
>すみません、これはどういうことなのでしょうか。

例題は悪いですが、以下のようなソースコードがあったとします。

--------------------------------------
int main()
{
int *a;
int h = 0;
printf("start\n");
for (;;) {
a = new int[16384];
h = h % 6;
if (h == 0){
Sleep(1);
}
if (h % 2 == 0){
delete[] a; //←hが1,3,5の時に呼ばれないため、メモリリークが発生する。
}
h++;
}
printf("end\n");
}

--------------------------------------
この場合、forループの中でnewは毎回呼ばれますが、deleteは2回に1回しか呼ばれません。
それでもaは毎回、新しく確保した領域のアドレスを保持するため2回に1回は確保したアドレスを何処にも保存することなく過ぎて行ってしまいます。
そのため、開放するために必要な情報(アドレス)が何処にも保存されていないためdeleteする事が出来なくなってしまいます。
結果、メモリリークが発生します。

またC++には例外処理があり、一見newした領域が必ずdeleteされるように見れるソースコードでもdeleteを通過せずに抜けてしまう場合があります。(以下ソースコード参照)

--------------------------------------
#include<stdio.h>
#include<stdlib.h>

class CMyReigai{
};


void func_a();

int main()
{
int *a;
try {
a = new int[1024];
func_a();
printf("normal end\n");
delete[] a;
}
catch( CMyReigai ex ){
printf("error end\n");
}
getchar();
}

void func_a()
{
CMyReigai b;
throw b;
}
--------------------------------------


デバッグモードで追っていけば分かりますが、func_aをコールした後、deleteが実行されずにcatchに処理が流れます。

上記の原因でメモリリークする場合もあります。。。
種類:アドバイス
どんな人:専門家
自信:参考意見
回答日時:09/10/17 01:38
回答番号:No.8
この回答への補足この回答に補足をつける(質問者のみ)
この回答へのお礼この回答にお礼をつける(質問者のみ)

回答

 

回答者:hiro_knigh お疲れ様です。

メモリリークだと思い、興味があって調べてみましたが結果はまだ出ていません。

メモリリークの原因としてはnewより、newで確保した領域がなんらかの原因でdeleteされていない方が多いと思います。

そこで、googleで「メモリリーク mfc」で検索してみました。


そうすると「DEBUG_NEW」に行き着きました。

「DEBUG_NEW」を定義すればメモリリークの検出手助けになると記載されているようですが、イマイチ使用方法が不明です。
そして、デバッグ版でコンパイルされた時のみしかつかえないようです。

あとは、malloc,free,new,deleteをラップして調べてみるしかないと思ったのですが、イマイチよいソースコードが記述出来ていません。

方法としては以下を考えています。
(1)newやmallocで確保した場合、確保したアドレスとソースコードのファイル名・ラインを保存
 (ファイル等で保存[アドレスはvoidにキャストして保存])
(2)deleteやfreeで開放したアドレスをキーに、(1)の対応した領域を削除

メモリリークが発生した時にファイルの中をのぞいて、同じ位置で確保し開放されていないエリアがたくさんあれば、その確保した処理に対する開放処理が無いか、何らかの原因で呼ばれなくなっているかだと思います。

興味があるのでもう少し調査や検討をしてみます。
もし、ご自身で分かられた場合は申し訳ありませんが方法を教えて頂けると幸いです。

メモリリークは10年ほど前にPL/Mでプログラムを組んでいた頃に経験はしましたが、デバッグは経験者にまかせてしまったので解決方法はイマイチ覚えていません。
種類:アドバイス
どんな人:専門家
自信:参考意見
回答日時:09/10/17 00:56
回答番号:No.7
参考URL: http://d.hatena.ne.jp/wata_d/20080304/1204609100
この回答への補足この回答に補足をつける(質問者のみ)
この回答へのお礼この回答にお礼をつける(質問者のみ)

回答

 

回答者:machongola  こんばんは。

 newの内部で「CMemoryExceptionクラス」が発生しているのではないでしょうか。
 ​http://msdn.microsoft.com/ja-jp/library/bc8b34bc(VS.80).aspx

 newを使用している箇所を以下の様にすれば特定し易くなると思います。

try
{
???* p = new ???(...);
}
catch(CMemoryException* e)
{
::MessageBox(NULL, NULL, NULL, IDOK);//●ココにポイントを張る
}
種類:アドバイス
どんな人:一般人
自信:参考意見
回答日時:09/10/16 19:09
回答番号:No.6
この回答への補足この回答に補足をつける(質問者のみ)
この回答へのお礼この回答にお礼をつける(質問者のみ)

回答

 

回答者:SilverThaw No.3です
>>まず、ダイアログに表示されているメッセージ内容を教えてください。
>そのダイアログに表示された内容は、
>タイトル     :XXXX(プロジェクト名です。(拡張子はついておりません。))
>メッセージ内容:Out of memory
典型的なメモリ管理(製造)ミスのメッセージですね。
ここでいう「メモリ」とはPCの「(OSが認識している)物理的な」メモリではなく、プログラムとして誤ったメモリ操作をしていることを意味しています。

>>No.2氏が書かれている通り、MFCやOSが出しているものではないですか?
>そうなのかも知れませんが、誰がどこで出しているか検討がついていないのが現状です。
やることはたった一つです。「原因の絞り込み」これだけです。
・実際にどのようにアプリを操作したら発生するのか
・アプリ発生時に動作している処理の特定
これを大きなところから、しだいに狭い領域に絞り込んでいきます。

プログラムは、そのプログラムだけで動作が簡潔しているのではなく、APIの呼び出し先はDLLとして別ファイル(プログラム)として存在します。
そういった箇所の問題であれば、いくら「ダイアログが出るから」と自分のソースの表示箇所だけを追いかけても永久にたどり着くことはできません。
種類:アドバイス
どんな人:一般人
自信:参考意見
回答日時:09/10/16 13:56
回答番号:No.5
この回答への補足この回答に補足をつける(質問者のみ)
この回答へのお礼この回答にお礼をつける(質問者のみ)

回答

 

回答者:php504 例えばRuntime errorとか
種類:アドバイス
どんな人:一般人
自信:参考意見
回答日時:09/10/16 12:17
回答番号:No.4
この回答への補足この回答に補足をつける(質問者のみ)
この回答へのお礼この回答にお礼をつける(質問者のみ)

回答

 

回答者:SilverThaw >ある条件になるとエラーを知らせるMessageBoxを出力するのですが、
そもそも、その「表示内容」はプログラム中で設定されている内容が表示されていますか?
No.2氏が書かれている通り、MFCやOSが出しているものではないですか?

まず、ダイアログに表示されているメッセージ内容を教えてください。
種類:補足要求
どんな人:一般人
自信:参考意見
回答日時:09/10/16 11:37
回答番号:No.3
この回答への補足ご回答、ありがとうございます。

本件は、以前も相談させていただきましたが、解決できなかったので、
再度質問させて頂いております。

>そもそも、その「表示内容」はプログラム中で設定されている内容が表示されていますか?
そのMessageBoxに書かれている内容は、プログラム中には発見できませんでした。

>No.2氏が書かれている通り、MFCやOSが出しているものではないですか?
そうなのかも知れませんが、誰がどこで出しているか検討がついていないのが現状です。

>まず、ダイアログに表示されているメッセージ内容を教えてください。
そのダイアログに表示された内容は、
タイトル     :XXXX(プロジェクト名です。(拡張子はついておりません。))
メッセージ内容:Out of memory
です。
この回答へのお礼この回答にお礼をつける(質問者のみ)

回答

 

回答者:titokani MessageBoxに表示されているメッセージを検索してみたら?
案外MFCとかが出しているMessageBoxとかもあるから、闇雲にブレークポイントを張るのは得策じゃないと思う。
種類:アドバイス
どんな人:専門家
自信:参考意見
回答日時:09/10/16 10:14
回答番号:No.2
この回答への補足ご回答、ありがとうございます。

MessageBoxに表示されているメッセージを検索しても
引っかからないのです。

>案外MFCとかが出しているMessageBoxとかもあるから、
これはどういうことなのでしょうか?
この回答へのお礼この回答にお礼をつける(質問者のみ)

回答

 

回答者:php504 DoModal( )でモーダルダイアログが表示できます。
種類:回答
どんな人:一般人
自信:参考意見
回答日時:09/10/16 07:39
回答番号:No.1
この回答への補足ご回答、ありがとうございます。

使用しているすべてのDoModal( )にブレイクポイントを
設定しても、引っかかりませんでした。
この回答へのお礼この回答にお礼をつける(質問者のみ)
最新から表示回答順に表示