トップページ⇒tech
94コメント37KB

リソースリーク対策

■ このスレッドは過去ログ倉庫に格納されています
0001デフォルトの名無しさんNGNG
普通のメモリリークなら、VCとかに標準でついてくる
チェック機能でかなりの部分を発見できるけれど、
GDI等のリソースリークはどのようにチェックしていますか?

NumegaやRationalのツールを使えばわかるけれど、ライセンス高価だし、
手軽に出来て、効果が期待できる方法ってないでしょうか
0044デフォルトの名無しさんNGNG
>>43
タスクトレイにアイコン突っ込みまくるプログラムを作れば
そのうちExplorerが落ちるってことですね。チャレンジしてみます。
0045デフォルトの名無しさんNGNG
自分で自分を起動する常駐アプリを作れば一瞬でわかります(藁
間違ってやったら途中で(120個位)起動できなくなった覚えあり(Win2000)
0046トリッキーの1NGNG
エクスプローラを落としたいならいくらでも方法があるだろうに(笑)

さて、面白い事を発見。Win9X系では、DeleteObjectの挙動が不穏です。
この関数は成功すればtrueを返すんだけれど、例えば
....
SelectObject(hMemDC,hBitmap);
....
BOOL b=DeleteObject(hBitmap);
ReleaseDC(hDC);
とかやると、ここでhBitmapの削除に失敗し
リソースリークが発生するにも関わらず、
なぜかb==1になってしまうのです。

と言うわけで、Purifyでも検出出来ませんでした(元々NT用だから話が違うけれど)。
これを検出するにはどうすればいいんだろう?

……今思いついたが、2回DeleteObjectをやってみるのは手かも知れない。
0047デフォルトの名無しさんNGNG
>>46

不穏なのは既出

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トリッキーの1NGNG
既出でしたか、失礼&情報源多謝
じゃ、NT系列でDeleteObjectの正否をチェックするか、
9xでDeleteObjectの複数成功をチェックするか、どちらかですね。

普通メモリリークを追跡する場合の開発環境は9x系列のはずなので、
後者の方向でチェックツール開発を進めてみます。
004931NGNG
>トリッキーの1

既にある大量のソース群ですか...
だったらマクロ使って自分で作った派生クラスを通すようにするのじゃダメ?
例えば、
#if _DEBUG // デバッグ時のみチェック
#define CDC CUserDC
#define CBrush CUserBrush
#endif
とする。

そんでCUserDCでどのオブジェクトが選択されているか、CUserBrushで
どのDCから選択されているかを記録しておく。
そうすればDCを開放する時に選択済みオブジェクトがあれば、非選択にした後に
開放できるんじゃないかと思った。

どうでしょう?

補足:DeleteObject()の戻り値を確実にチェックしておけばリークが見つかるんだけどね。
0050トリッキーの1NGNG
>>49=31
それだと、MFCにしか対応できないので辛いのですよ(参照>>2氏)
完全にMFCしか使っていなければ、もちろんそれで可能なのですが。
0051デフォルトの名無しさんNGNG
Javaを使えばリークしません。よくわかったか愚か者ども!!
0052デフォルトの名無しさんNGNG
ようわからんがタスクマネージャのGDIオブジェクトの値を見ときゃいいんか?
0053デフォルトの名無しさんNGNG
>>51
ハイハイ、自分の技術力の無さを認めたわけね。
ある意味潔くていいよ。
0054!!!警告!!!NGNG
〜java厨房徘徊中〜
0055デフォルトの名無しさんNGNG
やってることはあんまり変わらんぞ>54<オレモナー
0056トリッキーの1NGNG
>>52
やはり当然、オンザフライで警告を出したい。

>>51
マジレスすれば、C#を使えばこの種の問題は無くなる。
しかもJavaのように速度がネックになることも無い。
しかし汎用性は無くなる。まぁこの場合Windows特化なので
汎用性は話の外だからいいけどね
0057デフォルトの名無しさんNGNG
C#なんてJavaの下の下。比べ物にならない。
0058デフォルトの名無しさんNGNG
57なんて"トリッキーの1"氏の下の下。比べ物にならない。
0059デフォルトの名無しさんNGNG
>>51
サーバサイドで Singleton のコレクションにオブジェクトがんがん
突っ込んで削除しない VB 厨房上がりが多いんだが。
0060デフォルトの名無しさんNGNG
58なんて57氏の下の下。比べ物にならない。
0061デフォルトの名無しさんNGNG
ジサクジエンミグルシイ
0062デフォルトの名無しさんNGNG
どうも、Java厨です。

Javaって、streamのclose()を呼び忘れてると、finalizeされるまで
システムリソース(fdやsocket)を握ったままになりますね。マヌケです。
強制GCすればいいんですが、GCでfinalizeされるとは規定されてないし、
結構厄介だと思います。だけどJava最高!!!
0063デフォルトの名無しさんNGNG
スレの方向性がずれまくり

というわけで、案外API拡張はまともなアイデアかもしれません
しかしモジュールごとにフックする必要がなぜあるのかわかりません。
APIって皆同じコードが呼ばれているんじゃないの?
0064デフォルトの名無しさんNGNG
ジサクジエンミグルシイ
0065デフォルトの名無しさんNGNG
メモリーリークの対策をプログラマーがやらないといけない言語なんて
もう古いよ。
0066デフォルトの名無しさんNGNG
メモリーリークっつうかリソースリークの話題だけどな。>>65
006731NGNG
ええい、WinAPI用だと以下の対策でどうでしょうか?

#if _DEBUG // デバッグ時のみチェック
#define SelectObject UserSelectObject
#define DeleteObject UserObjectDC
#define DeleteDC UserDeleteDC
#define ReleaseDC UserReleaseDC
#endif

あとはCreatePenとかのオブジェクト作成関数もラッパすれば完全では?

つか、この手のものは1本ソース書いておけばいろんなプロジェクトで使いまわしできるんだし、
身の回りの誰かが作っていたりして。
0068トリッキーの1NGNG
>>67=31
それだと、
CDC *pDC;
..
pDC->SelectObject(hBrush); // アウト
0069デフォルトの名無しさんNGNG
どうも、Java厨です。

>>66
ええ、そのとおりです。メモリーリークでなく「リソース」リークですね。
実行中のリソース解放し忘れは、Javaであっても鬼門なんです。
なんせgc/finalizeの実装に依存しちゃいますからね!でもJava最高!
0070デフォルトの名無しさんNGNG
2年目の JDBC ほとんどやったことない奴が中途半端なDBアクセス
のスーパークラスを作ったおかげでリソースリークでまくりです。
30 分も動かしているとアプリケーションとまっちゃいます。
うんこ。






                              うんこ。
007170NGNG
アプリケーション → アプリケーションサーバ
ひどく疲れているようだ...
0072デフォルトの名無しさんNGNG
>>71
どちらかというと> うんこ。を二つも書く辺りに取り返しのつかない疲労を感じる
0073デフォルトの名無しさんNGNG
>>67
CUserDC:CUserSelectObjectになっちゃいます

この方向のアプローチはデバッグ版ではリークしないのにリリース版で
リークするという現象が発生したときどうにもならないし
0074デフォルトの名無しさんNGNG
ところで

>>56 (C#)
>しかもJavaのように速度がネックになることも無い。

これ本当ですか?何故そうなるっすか?Javaとそんなに違うっすか?
0075デフォルトの名無しさんNGNG
>>74 嘘に決まってんだろ。Java よりも速いと歌ってのはまだモノも出来てない
話題沸騰中の頃のセールストークだよ。それを信じたまま今日まで来てる C/C++
信者多すぎ。
0076デフォルトの名無しさんNGNG
>>75
C/C++信者 → MS信者

Javaの、まだモノも出来てない話題沸騰中の頃のセールストークも酷かったねえ...
0077デフォルトの名無しさんNGNG
C#はJavaより低速だよ。Javaのほうが歴史が長い分最適化されてる。
0078トリッキーの1NGNG
なんか、俺のC#の認識がずれてる気がしたので、
スレ違いだけれどちょっと確認させてください。

セールストークとβ版によれば、
・VMを介しないのでコードが高速(利点)
・標準ライブラリが充実(必須)
・ネイティブコード依存(欠点)
なので、クロスプラットフォームが多少関わるWeb系は今まで通りJavaで、
Windows系のGUIプログラムはC#に移行していく、と思われます。

Javaを使い続ける限り、どんなにCPUが高速になったところで、
速度で「VMを介する」というネックを避けることが出来ないので、
Windowsネイティブに限ればC#で開発するメリットは非常に大きいでしょう。
しかし、速度よりも移植性が大事なWeb系のプログラミングでは、
IISでしか使えないであろうC#にわざわざ乗り換える人も少ないでしょう。

(仮にLinux上などで環境が整えば、一気にC#の価値が高まるでしょうね)

コレについて、具体的に「この点が違うよ」というのがあれば教えてください。
この話題についてはsage進行でいきませう。
0079ななC#NGNG
>>77
最適化については、直感的にC#の方が優れているような。
言語の歴史では明らかにCの方が長いし、
C#とJavaは同じ最適化理論を使える(オブジェクト言語最適化)し、
歴史的にMSは開発環境だけはいいものを提供してくれるし。

C#が低速というのは、実験した結果?だとするとそうかもしれないけど。
ま、製品版がリリースされるまで解らないな
0080デフォルトの名無しさんNGNG
>>78
> ・VMを介しないのでコードが高速(利点)
CLRってのはVMだろ。
0081トリッキーの1NGNG
CLR知りませんでした。
こんな知識でC#について語る資格はありませんね。
ごめんなさい。

しかしまぁ、Javaの様な汎用的なVMではなく、
Windowsに特化したVMして速度改善を達成するのでは、と
思われるのですが、その情報をご存じの方は?

というか、やっぱりC#はC#スレでやるべきですね。
このスレで不用意なC#の発言をしてしまい、結果荒らしてしまいすみません>1さん
008231NGNG
>>68
MFCじゃなくてAPIの場合の話だったのに...
ちなみに「漏れなくラッパする」って考え自体がまずいの?

>>73
デバッグ版とリリース版で動作が違う時ってどんな場合があったっけ?
変数の未初期化での使用とか配列でちょっとオーバーして使った場合とかは経験あるけど。
まぁそういうのはツール使えば発見できるんだけど、それじゃぁ本末転倒だし。
0083トリッキーの1NGNG
>>82
そうじゃなくて、そんなdefineをすると、
APIじゃない部分でコンパイルが出来なくなるよ、ということ。
完全MFC or 完全APIで書かれていたら問題はないけれど、
両者が混在している場合も十分考えられるでしょ?

もれなくラッパ出来るならば一番いいんだけれど、
多分API自身をラッパする以外の方法では無理だと思われます。
008431NGNG
>>83

なるほどねー
まぁチェックルーチンを後付けだとうまく行かない部分もあるかも。
理想的には開発時にチェックルーチン付けちゃえば問題ないんだけど。
0085トリッキーの1NGNG
開発時にチェックルーチンを付けるなら、
所有権付きのスマートポインタもどきでハンドルクラスを実装すると
結構うまく行くんじゃないのかな?
その場合の所有権は、DCに対応する感じで。
誰か既に作ってそうだけれど、ご存じの方は?
0086デフォルトの名無しさんNGNG
安芸
0087デフォルトの名無しさんNGNG
>>85
すでにチェックを行うためじゃなくてそれで管理行っちゃった方がよいと思うが
0088デフォルトの名無しさんNGNG
BoundsCheckerもどきを自作する
0089デフォルトの名無しさんNGNG
結局、リソースのオーナをしっかり決め、管理する仕掛けが必要って事だな
0090デフォルトの名無しさんNGNG
>>56
いまさらで悪いんですが、C#ならリソースリーク防げるってのは、
VCLを使えばリーク防げる/VBを使えばリソース管理を気にする必要がない、
と言うのと同様の問題を含んでません?

APIを使うって事は、要はその開発環境の標準ライブラリだけじゃ実装しきれ
ない状況に追い込まれて仕方がなく使用するわけだから、C#になっても、結局
は(ポインタ使用可能なモードにしての)ポインタの管理、或いはそれに準ず
る問題に行きつく気がするんですけど。
0091デフォルトの名無しさんNGNG
>>90
実際ソノトオリ行けるかどうかは別として一般論に過ぎないが、
JNIやポインタ使用可能モードなC#やrubyの拡張ライブラリ(藁)みたいなものが
うまくいくかどうか?は、それらのクラスライブラリが拡張ライブラリに対して、
いかにハマリ「にくい」モデル(Frameworkといってもいい)を提供してくれてるか?に
かかっている、という面が有るように思える。

標準ライブラリが無ければ常に丸裸だ、というほどまでに
プログラミングの世の中は冷たくもなければAllOrNothingでもない。
というか、そんなつかえねぇ環境は滅びやがれってかんじ。

フレームワークっていう考え方が重要だよ。
ライブラリといわば逆の考え方。
ライブラリは他人が作ったサブを自分が作ったメインが呼ぶ。
フレームワークは自分が作ったサブを他人が作ったメインが呼ぶ。
0092デフォルトの名無しさんNGNG
VCLにしても、
APIで欲しいリソースをVCLから貰うという方法でリークはだいぶ防げる筈
0093デフォルトの名無しさんNGNG
リソースリークとメモリリークを混同していいものか・・・
0094デフォルトの名無しさん01/08/26 21:36ID:SM0Vd3m6
保存sage
■ このスレッドは過去ログ倉庫に格納されています