リソースリーク対策
■ このスレッドは過去ログ倉庫に格納されています
0001デフォルトの名無しさん
NGNGチェック機能でかなりの部分を発見できるけれど、
GDI等のリソースリークはどのようにチェックしていますか?
NumegaやRationalのツールを使えばわかるけれど、ライセンス高価だし、
手軽に出来て、効果が期待できる方法ってないでしょうか
0002デフォルトの名無しさん
NGNGでも普通にハンドルをやりとりしている部分は必ず出るし、
そういう所のチェックにいい方法はないのかなぁ
ハンドルをスマートポインタで実装……とか考えたけど、
よく考えればハンドルって32bitの整数だしなぁ
0003トリッキーの1
NGNGしかし全てのGDI関数についてAPIラップを作るのは骨が折れるな。
生成と破棄が絡む部分だけでいいんだけれど、SelectObjectとか
死にたくなるほど大変だ。
……大体、APIのラップってどうやって作るんだ?
#define CreatePen MyCreatePen
とかやったりしたら、
CPen::CreatePen
とかで死亡するし。
勢いだけで書いて自己完結してしまった
0004トリッキーの1
NGNGしかしその場合、外部プログラムで記述するしか方法が無くなるな。
そうすると、ようやくメモリリークが見つかったとしても、
どこで起きたのか特定することが出来なくなるな。デバッグが大変だ。
どなたか優秀な方、
自分自身の呼びだすWindowsAPIのフックの方法を教えて下さい。
0005デフォルトの名無しさん
NGNGインポートライブラリを作えばいいじゃん
0006トリッキーの1
NGNGいいわけですか。なるほど、確かにそうだ。
VC++ならgdi32.libを使用しなければいいわけですね。
使用しない関数は全部丸投げすればいいわけですし……
ちょっと実験してみよう、ナイス助言サンクス
0007デフォルトの名無しさん
NGNGVC方面でばかり聞くんだけどさ(笑)、
つまりこれは出来がよい(この場合はリソースリークの少ない)クラスライブラリの
有無の問題であるわけっすか?
ラッパー層は、必ずしも薄くしないとパフォーマンスが(有為に)下がる
とは言いきれないし。
誰か、ばしっと、マシなライブラリを作らない(作れない)んですか?
0008デフォルトの名無しさん
NGNGたしかにVBやDelphiやC++Builderではきかないね。
VCLはリソース管理は徹底してるしMFCみたいにユーザに
SelectObjectとかをいじらせてないな。
0010デフォルトの名無しさん
NGNGMFC というより、Win32 API を直接叩くかどうかの差だね。
直接 Win32 API を使うなら、必然的にリソース管理はプログラマの側
に降ってくるし(代わりにプログラマの自由度があがる、速度はいまど
き大差ないかも)し、API を一切使わせずにクラスライブラリのフレー
ムワーク内で対処するならリソース管理はクラスライブラリの責任にな
る。
それと、どうも Delphi ユーザの一部に、いちいち無関係なスレッドに
出てきて VC ユーザに喧嘩を売るような口調で書き込む人間がいるんだ
けど、荒れるからやめてほしいな(もしかして C++ で template 使
うとコード量が爆発するとか言ってたのと同一人物?)
0011デフォルトの名無しさん
NGNG0012デフォルトの名無しさん
NGNG後、>>5の言っている意味はわかるけれど、
どうやってやるのか知りたい
0013トリッキーの1
NGNGインポートライブラリを外から作るのが難しい。
VCなんですが、例えば
__declspec(dllexport)
HPEN __stdcall MyCreatePen(...){MessageBeep(0);CreatePen(...);}
というものを作って、DEFファイルで
EXPORTS CreatePen=MyCreatePen
とやって、フックされる方でgdi32.libを読み込まず作ったlibを指定しても、
リンクで外部参照のエラーが発生します。
libを見たところ、exportはちゃんとされてるっぽいんだけれど……
眠いので続きは後でやろっと。
もしものすごい間抜けな事をしていたら、誰か突っ込んで下さい。
dllまわりはほとんど知識がないので、是非是非
0014デフォルトの名無しさん
NGNG昔あったらしいね。Winで。
0015デフォルトの名無しさん
NGNGというか、MFCでもなく、かといってアプリ作成個人(または法人)が
毎回作るでもない、というクラスライブラリを、
誰かサードパーティ(商用かFREEかは別として)が作ったりした実績は
無いものなんでしょうか?
MFCはあんまり高級じゃないと聞くけど、
じゃあ誰かが作った高級ライブラリをその上にかぶせて、
そいつがデファクトスタンダードになったり、とかは
しないものなのかな、と。
>C++ で template
ああ。あれ?厨と一緒にせんで。
00168
NGNGただ、プログラマの労力を軽減するのがフレームワークであり、
クラスライブラリでしょ?ってことで。
0017デフォルトの名無しさん
NGNG0018デフォルトの名無しさん
NGNGしかしスレの趣旨とずれ始めているので深く書くのはやめておきます。
知りたい人もいないだろうし。
0019デフォルトの名無しさん
NGNG0020デフォルトの名無しさん
NGNG1をよく読もう
0021デフォルトの名無しさん
NGNG0022デフォルトの名無しさん
NGNG>1
>普通のメモリリークなら、VCとかに標準でついてくる
>チェック機能でかなりの部分を発見できるけれど、
これってなんのこと?
0023デフォルトの名無しさん
NGNGデフォルトではメモリブロック識別子しか有効にならないんだけど、フ
ラグを設定すれば malloc(), free() 時にヒープが壊れていないかチェ
ックしたり、プログラム終了時に解放されていないメモリ領域をダンプ
できます。
_CrtSetDbgFlag(_CRTDBG_ALLOC_MEM_DF | _CRTDBG_CHECK_ALWAYS_DF | _CRTDBG_LEAK_CHECK_DF);
私がプログラムを書くときのデフォルトは↑こんな感じ。
002422>23
NGNGつっても最近Visual StudioでPerlとRubyしか書いてないけど(藁
0025トリッキーの1
NGNGGDIまわりのハンドルの移動を大体掴むことが出来ました。
解放し忘れのGDIObjectをちゃんと表示できます。
しかし、DLLとかが絡んでくると厄介。
例えば、sample.exeはgdi32.dllとoriginal.dllとmfc42.dllをインポートしているとして、
とりあえずここのgdi32.dllをフックしたとしても、それだけでは足りなくて
mfc42.dllにインポートされているgdi32.dllもフックする必要があるし、
もしoriginal.dllがmfc42.dllとgdi32.dllをインポートしていたら……
とか考え出すと、全部にフックをかけるだけで果たしていいのか不安になります。
ま、暇な時に続きを作ってみます。
0026デフォルトの名無しさん
NGNGという方法もある。
これ使ってkernel32.dllをオーバーライドして日付を狂わし、
シェアウェアの使用期限を延ばす、なんちて。
0027トリッキーの1
NGNG過去レスにもあったけれど、その場合って
GDI32.DLLを完全にサポートした疑似DLLが必要になるんじゃないですか?
(もちろんインターフェースだけで、内容は本物にまわせばいいわけですが)
それを作るならフックの方が早いかな、なんて思ったり
0028デフォルトの名無しさん
NGNG0029
NGNG自分で作るexeとdllに全てそれぞれ内部でフックさせればいいのでわわわ?
0030トリッキーの1
NGNGその共有DLLの内部でGDIリソースリークが起こったら問題がおきるのでは?
CBrush *p=new CBrush(RGB(0,0,0));
delete p;
みたいな。
0031
NGNGCBrushのデストラクタで開放してくれているんじゃないの?
まぁSelectされたままでは出来ないのかも知れんが。
最悪でもCDCとCBrushの派生クラスを作ってチェックすればいいと思います。
0032デフォルトの名無しさん
NGNGハクるってなによ?
ヴァカじゃねーの!(ワラ
0033トリッキーの1
NGNGああ、確かにこのコードだとデストラクタが呼ばれるか。
deleteが無ければ……メモリリークか(笑)
何にしても、言いたいのはMFCについてではなく、
自分の作ったEXEやDLLだけフックしても完全では無いぞ、と言うことです。
派生クラスの話をしたら、ハンドルをスマートポインタで実装したら
すべて解決してしまうので、ここでは既にある巨大なソース群に対し
簡単にチェックする方法を考えてみましょう。
0034デフォルトの名無しさん
NGNGWINEとかReactOSとかかな。Reactはおいておいて、
あれはそれ以前にその環境でアプリをまず動かすように
するほうが大変かな。
でもWINEとかでVisualC++が動いているのをみるとあながち
不可能ではないかも。
Windowsに標準でリソースリークの警告機能ぐらいあっても
よいのに・・・デバッグ版windowsではあるのかな?
>>32
まぁわかんない人には永遠にわかんないでよい言葉だ。
0035デフォルトの名無しさん
NGNGた
たしかにアプリが解放しないで終了したリソースはOSが解放しなければならない
ってのはそうなんだけど、それをアテにするべきかは、、、って
この話題はやめておきましょうか。なんか他のスレであれているのを
見たような気がする。
0036デフォルトの名無しさん
NGNG一度走ってすぐ終了するプログラムなら、
リソースの解放なんてしなくてもいいと思うんだけども。
makeとか。
0037デフォルトの名無しさん
NGNG0038デフォルトの名無しさん
NGNG最悪還元時にfinally起動するとか。
0039デフォルトの名無しさん
NGNGこの話題って、fj.comp.lang.cの恥さらしネタだな(藁
アプリが終了後に「OSが」責任もって食べ残しを始末してくれるタイプの餌については
それ(>>36)でいいって奴。現にそれが達成されてないOSでやらなきゃならない仕事が
有るならば、別の手段…つまり厳密な解放の策を講じないとならん。
>>38
某GCライブラリをあてにしてたら、終了時に残ったものが解放されなくて焦った(藁
終了の直前までは領域を指すポインタが生きてる(Global変数とかなら特に)からGCされないし、
終了しちゃったらそもそもGCもへったくれもない。
結果として解放するチャンスがない(藁
結局この問題にとって必要なのは、例外というよりもfinallyつまり後始末の仕掛け(だけ)。
もちろん、プログラム動いてる「途中」のものを解放させるためにはGCは効果的だが。
WeakPointerを持ったCollectionに結び付けておいて、at_exitで明示的解放をさせる、
とかをすれば有効かな。
0040デフォルトの名無しさん
NGNG0041デフォルトの名無しさん
NGNGWindows環境でのリソースリーク対策の話をしているのではないの?
0042デフォルトの名無しさん
NGNG95や95OSR2の時代はWinsockやRAS絡みであったらしいけど、今特に目立つものは無い。
よって39の仮定はもはや意味なし。39は巣に帰りましょう。
継続的な動作をするプログラムでのリソースリーク対策
ならば、有益な話が期待できそう。
0043デフォルトの名無しさん
NGNGタスクトレイのアイコンとかかな。
でも仕様って逝ってしまえばそれまでかもなー
0044デフォルトの名無しさん
NGNGタスクトレイにアイコン突っ込みまくるプログラムを作れば
そのうちExplorerが落ちるってことですね。チャレンジしてみます。
0045デフォルトの名無しさん
NGNG間違ってやったら途中で(120個位)起動できなくなった覚えあり(Win2000)
0046トリッキーの1
NGNGさて、面白い事を発見。Win9X系では、DeleteObjectの挙動が不穏です。
この関数は成功すればtrueを返すんだけれど、例えば
....
SelectObject(hMemDC,hBitmap);
....
BOOL b=DeleteObject(hBitmap);
ReleaseDC(hDC);
とかやると、ここでhBitmapの削除に失敗し
リソースリークが発生するにも関わらず、
なぜかb==1になってしまうのです。
と言うわけで、Purifyでも検出出来ませんでした(元々NT用だから話が違うけれど)。
これを検出するにはどうすればいいんだろう?
……今思いついたが、2回DeleteObjectをやってみるのは手かも知れない。
0047デフォルトの名無しさん
NGNG不穏なのは既出
http://www.microsoft.com/JAPAN/support/kb/articles/J024/2/17.htm?LN=JA&SD=SO&FR=0
> Windows 95 では、SeleteObject() で DC に選択されているときに GDI
> 描画オブジェクトを削除しようとすると DeleteObject() への呼び出しが
> 正常終了します。
>
> しかし呼び出しが正常に終了しても実際には削除されていません。Windows NT
> では DC に選択された GDI オブジェクトで DeleteObject() への呼び出しを
> 行うと失敗します。 DeleteObject を呼び出す前には GDI オブジェクトの
> 選択を常にクリアする必要があります。
0048トリッキーの1
NGNGじゃ、NT系列でDeleteObjectの正否をチェックするか、
9xでDeleteObjectの複数成功をチェックするか、どちらかですね。
普通メモリリークを追跡する場合の開発環境は9x系列のはずなので、
後者の方向でチェックツール開発を進めてみます。
004931
NGNG既にある大量のソース群ですか...
だったらマクロ使って自分で作った派生クラスを通すようにするのじゃダメ?
例えば、
#if _DEBUG // デバッグ時のみチェック
#define CDC CUserDC
#define CBrush CUserBrush
#endif
とする。
そんでCUserDCでどのオブジェクトが選択されているか、CUserBrushで
どのDCから選択されているかを記録しておく。
そうすればDCを開放する時に選択済みオブジェクトがあれば、非選択にした後に
開放できるんじゃないかと思った。
どうでしょう?
補足:DeleteObject()の戻り値を確実にチェックしておけばリークが見つかるんだけどね。
0051デフォルトの名無しさん
NGNG0052デフォルトの名無しさん
NGNG0053デフォルトの名無しさん
NGNGハイハイ、自分の技術力の無さを認めたわけね。
ある意味潔くていいよ。
0054!!!警告!!!
NGNG0055デフォルトの名無しさん
NGNG0056トリッキーの1
NGNGやはり当然、オンザフライで警告を出したい。
>>51
マジレスすれば、C#を使えばこの種の問題は無くなる。
しかもJavaのように速度がネックになることも無い。
しかし汎用性は無くなる。まぁこの場合Windows特化なので
汎用性は話の外だからいいけどね
0057デフォルトの名無しさん
NGNG0058デフォルトの名無しさん
NGNG0059デフォルトの名無しさん
NGNGサーバサイドで Singleton のコレクションにオブジェクトがんがん
突っ込んで削除しない VB 厨房上がりが多いんだが。
0060デフォルトの名無しさん
NGNG0061デフォルトの名無しさん
NGNG0062デフォルトの名無しさん
NGNGJavaって、streamのclose()を呼び忘れてると、finalizeされるまで
システムリソース(fdやsocket)を握ったままになりますね。マヌケです。
強制GCすればいいんですが、GCでfinalizeされるとは規定されてないし、
結構厄介だと思います。だけどJava最高!!!
0063デフォルトの名無しさん
NGNGというわけで、案外API拡張はまともなアイデアかもしれません
しかしモジュールごとにフックする必要がなぜあるのかわかりません。
APIって皆同じコードが呼ばれているんじゃないの?
0064デフォルトの名無しさん
NGNG0065デフォルトの名無しさん
NGNGもう古いよ。
0066デフォルトの名無しさん
NGNG006731
NGNG#if _DEBUG // デバッグ時のみチェック
#define SelectObject UserSelectObject
#define DeleteObject UserObjectDC
#define DeleteDC UserDeleteDC
#define ReleaseDC UserReleaseDC
#endif
あとはCreatePenとかのオブジェクト作成関数もラッパすれば完全では?
つか、この手のものは1本ソース書いておけばいろんなプロジェクトで使いまわしできるんだし、
身の回りの誰かが作っていたりして。
0068トリッキーの1
NGNGそれだと、
CDC *pDC;
..
pDC->SelectObject(hBrush); // アウト
0069デフォルトの名無しさん
NGNG>>66
ええ、そのとおりです。メモリーリークでなく「リソース」リークですね。
実行中のリソース解放し忘れは、Javaであっても鬼門なんです。
なんせgc/finalizeの実装に依存しちゃいますからね!でもJava最高!
0070デフォルトの名無しさん
NGNGのスーパークラスを作ったおかげでリソースリークでまくりです。
30 分も動かしているとアプリケーションとまっちゃいます。
うんこ。
うんこ。
007170
NGNGひどく疲れているようだ...
0072デフォルトの名無しさん
NGNGどちらかというと> うんこ。を二つも書く辺りに取り返しのつかない疲労を感じる
0073デフォルトの名無しさん
NGNGCUserDC:CUserSelectObjectになっちゃいます
この方向のアプローチはデバッグ版ではリークしないのにリリース版で
リークするという現象が発生したときどうにもならないし
0074デフォルトの名無しさん
NGNG>>56 (C#)
>しかもJavaのように速度がネックになることも無い。
これ本当ですか?何故そうなるっすか?Javaとそんなに違うっすか?
0075デフォルトの名無しさん
NGNG話題沸騰中の頃のセールストークだよ。それを信じたまま今日まで来てる C/C++
信者多すぎ。
0076デフォルトの名無しさん
NGNGC/C++信者 → MS信者
Javaの、まだモノも出来てない話題沸騰中の頃のセールストークも酷かったねえ...
0077デフォルトの名無しさん
NGNG0078トリッキーの1
NGNGスレ違いだけれどちょっと確認させてください。
セールストークとβ版によれば、
・VMを介しないのでコードが高速(利点)
・標準ライブラリが充実(必須)
・ネイティブコード依存(欠点)
なので、クロスプラットフォームが多少関わるWeb系は今まで通りJavaで、
Windows系のGUIプログラムはC#に移行していく、と思われます。
Javaを使い続ける限り、どんなにCPUが高速になったところで、
速度で「VMを介する」というネックを避けることが出来ないので、
Windowsネイティブに限ればC#で開発するメリットは非常に大きいでしょう。
しかし、速度よりも移植性が大事なWeb系のプログラミングでは、
IISでしか使えないであろうC#にわざわざ乗り換える人も少ないでしょう。
(仮にLinux上などで環境が整えば、一気にC#の価値が高まるでしょうね)
コレについて、具体的に「この点が違うよ」というのがあれば教えてください。
この話題についてはsage進行でいきませう。
0079ななC#
NGNG最適化については、直感的にC#の方が優れているような。
言語の歴史では明らかにCの方が長いし、
C#とJavaは同じ最適化理論を使える(オブジェクト言語最適化)し、
歴史的にMSは開発環境だけはいいものを提供してくれるし。
C#が低速というのは、実験した結果?だとするとそうかもしれないけど。
ま、製品版がリリースされるまで解らないな
0080デフォルトの名無しさん
NGNG> ・VMを介しないのでコードが高速(利点)
CLRってのはVMだろ。
0081トリッキーの1
NGNGこんな知識でC#について語る資格はありませんね。
ごめんなさい。
しかしまぁ、Javaの様な汎用的なVMではなく、
Windowsに特化したVMして速度改善を達成するのでは、と
思われるのですが、その情報をご存じの方は?
というか、やっぱりC#はC#スレでやるべきですね。
このスレで不用意なC#の発言をしてしまい、結果荒らしてしまいすみません>1さん
008231
NGNGMFCじゃなくてAPIの場合の話だったのに...
ちなみに「漏れなくラッパする」って考え自体がまずいの?
>>73
デバッグ版とリリース版で動作が違う時ってどんな場合があったっけ?
変数の未初期化での使用とか配列でちょっとオーバーして使った場合とかは経験あるけど。
まぁそういうのはツール使えば発見できるんだけど、それじゃぁ本末転倒だし。
0083トリッキーの1
NGNGそうじゃなくて、そんなdefineをすると、
APIじゃない部分でコンパイルが出来なくなるよ、ということ。
完全MFC or 完全APIで書かれていたら問題はないけれど、
両者が混在している場合も十分考えられるでしょ?
もれなくラッパ出来るならば一番いいんだけれど、
多分API自身をラッパする以外の方法では無理だと思われます。
008431
NGNGなるほどねー
まぁチェックルーチンを後付けだとうまく行かない部分もあるかも。
理想的には開発時にチェックルーチン付けちゃえば問題ないんだけど。
0085トリッキーの1
NGNG所有権付きのスマートポインタもどきでハンドルクラスを実装すると
結構うまく行くんじゃないのかな?
その場合の所有権は、DCに対応する感じで。
誰か既に作ってそうだけれど、ご存じの方は?
0086デフォルトの名無しさん
NGNG0087デフォルトの名無しさん
NGNGすでにチェックを行うためじゃなくてそれで管理行っちゃった方がよいと思うが
0088デフォルトの名無しさん
NGNG0089デフォルトの名無しさん
NGNG0090デフォルトの名無しさん
NGNGいまさらで悪いんですが、C#ならリソースリーク防げるってのは、
VCLを使えばリーク防げる/VBを使えばリソース管理を気にする必要がない、
と言うのと同様の問題を含んでません?
APIを使うって事は、要はその開発環境の標準ライブラリだけじゃ実装しきれ
ない状況に追い込まれて仕方がなく使用するわけだから、C#になっても、結局
は(ポインタ使用可能なモードにしての)ポインタの管理、或いはそれに準ず
る問題に行きつく気がするんですけど。
0091デフォルトの名無しさん
NGNG実際ソノトオリ行けるかどうかは別として一般論に過ぎないが、
JNIやポインタ使用可能モードなC#やrubyの拡張ライブラリ(藁)みたいなものが
うまくいくかどうか?は、それらのクラスライブラリが拡張ライブラリに対して、
いかにハマリ「にくい」モデル(Frameworkといってもいい)を提供してくれてるか?に
かかっている、という面が有るように思える。
標準ライブラリが無ければ常に丸裸だ、というほどまでに
プログラミングの世の中は冷たくもなければAllOrNothingでもない。
というか、そんなつかえねぇ環境は滅びやがれってかんじ。
フレームワークっていう考え方が重要だよ。
ライブラリといわば逆の考え方。
ライブラリは他人が作ったサブを自分が作ったメインが呼ぶ。
フレームワークは自分が作ったサブを他人が作ったメインが呼ぶ。
0092デフォルトの名無しさん
NGNGAPIで欲しいリソースをVCLから貰うという方法でリークはだいぶ防げる筈
0093デフォルトの名無しさん
NGNG0094デフォルトの名無しさん
01/08/26 21:36ID:SM0Vd3m6■ このスレッドは過去ログ倉庫に格納されています