madapaja回答ポイント 150ptウォッチ 1

開発環境:C++ Builder 2009(WinXPPro)


別スレッドから、一定時間毎にフォーム上に配置したTImageの内容を
書き換える処理を行っているのですが、たまに、EOutOfResourcesエラーが発生します。

TImageのハンドルが取得できなくなっているのではないか、と思うのですが、
どのように対処すればいいのかわかりません。

・別スレッドで行っているのは、下記のような内容です。
Graphics::TBitmap bmpBuffer;
//---------------------------------------------------------------------------
void __fastcall thread_proc::Execute()
{
bmpBuffer = new Graphics::TBitmap();
bmpBuffer->HandleType = bmDIB;
bmpBuffer->PixelFormat = pf1bit;
bmpBuffer->SetSize(100, 300);

while(true) {
// bmpBuffer->Canvasを使用した描画処理

Synchronize(&ImgUpdate);

i++;
Sleep(100);
}

delete bmpBuffer;
}
//---------------------------------------------------------------------------
void __fastcall thread_proc::ImgUpdate()
{
Form1->ImgPrev->Picture->Bitmap->Assign(bmpBuffer);
}

わかる方がいらっしゃいましたら、ご教授いただければと思います。
よろしくお願いします。

※ 有料アンケート・ポイント付き質問機能は2023年2月28日に終了しました。
ログインして回答する

アニメーション?

tdoi2009-09-02 17:34:31

ソースから判断すると、左下に動いていくようなアニメーションを表示したいのですか?

元の描画がどのように行っているのかわからないですが、

CopyRectを呼び出すインスタンスと、CopyRectの第2引数のインスタンスが同一でもいいのでしょうか?

これがAPIでサポートされているかは分かりますか?


これで解決するかどうかも分かりませんが、オリジナルの絵を持ったTBitmapオブジェクトを作成しておいて、この処理を通るたびに、SrcRectの値と、DstRectの値を変えて、そのオリジナルのTBitmapのTCanvasから、上記のソース中のbmpBufferのTBitmapの持つTCanvasにコピーするようにしたらどうでしょうか?


全体が見えないので、原因も明確に見えないので、はずしている可能性は大ですが。

CopyRect時にEOutOfResources例外

madapaja2009-09-02 01:43:12

回答ありがとうございます。

try/catchを使って、例外が発生する箇所の特定を試みたところ、

  // bmpBuffer->Canvasを使用した描画処理

部分で行っているCopyRectにて、EOutOfResources例外が発生しているようでした。

//該当部分のソース

TRect SrcRect, DstRect;

SrcRect = Rect(0, 0, 100, 300 - 8);

DstRect = Rect(0, 8, 100, 300);

try {

bmpBuffer->Canvas->CopyRect(DstRect, bmpBuffer->Canvas, SrcRect);

} catch (EOutOfResources &e) {

ShowMessage("EOutOfResources at CopyRect");

}

なぜ、このようになるのかわからないのですが、引き続き調査したいと思います。

例外なら・・・

tdoi2009-09-01 15:09:46

Borland提供のAPIは詳しくないので、はずしていたら申し訳ないですが、

あやしいところをtry/catchで囲めばいいのでは?

try {

bmpBuffer = new Graphics::TBitmap();

} catch (EOutOfResources e) {

//エラーメッセージ

}

これで、エラーメッセージがでれば、TBitmapのコンストラクタが例外を投げていると分かるでしょう。

明らかにあやしい処理があれば、こんな感じでピンポイントでチェックして、それで見つからなければ、try/catchの範囲を色々変えてみればいかがですか?

何かの参考になれば。

ご回答ありがとうございます。

madapaja2009-09-01 13:47:20

知識不足でEOutOfResources例外が投げられる場所を特定する方法がわかりませんでした。。。

いただいた内容(推測ではなく原因を調査する必要があるという点)はごもっともだと思いますので、

何とか例外がおきている箇所を特定する方法を模索したいと思います。

ご回答いただき、ありがとうございました!

回答ありがとうございます

madapaja2009-09-01 13:45:09

いただいた方法を元に、全GDI数を計算した所、2000強でした。

また、作成したアプリケーションのみのGDI数は55程度で、GDI数に引っかかっているようではありませんでした。

引き続き、原因を調査したいと思います。

ご回答いただき、ありがとうございました!

リソースリーク?

cx202009-09-01 00:46:50

C++ Builder は使ったことはありませんが、以下が原因ではないでしょうか?


Windows の仕様で「プロセス毎の GDI オブジェクト数」の制限(Windows 2000/XP の既定値:10,000個)というのがあります。

通常、使用した GDI オブジェクトを正しく開放していれば、問題ありませんが、取得して開放しなかったりすると、だんだんリークしていって、リソースが足りなくなります。


GDI オブジェクト数は、タスクマネージャで確認することができます。

該当プロセスの GDI オブジェクト数が 9,999 個に達していないか確認してみてください。

<GDI オブジェクト数の確認方法>
1. [Ctrl] + [Shift] + [ESC] にて「タスクマネージャ」を起動します。
2. [表示] - [列の選択] メニューを選択します。
3. 「列の選択」ダイアログにて [GDI オブジェクト] にチェックを入れ [OK] ボタンを押下します。
<参考情報>
■ Windows XP または Windows 2000 でプロセスが GDI オブジェクト クォータを超えた場合、
デスクトップのアプリケーション メニューが正しく表示されない
http://support.microsoft.com/kb/838283/ja
■ はてブ閲覧時のリソース不足
http://q.hatena.ne.jp/1227957618

と思うという、想像ではなく

tdoi2009-08-31 18:42:24

まずは、EOutOfResourcesの例外が投げられる場所を特定してはどうですか?

対処法の前に、原因を確定させないと難しいでしょう。

この質問へのコメント

コメントはありません

この質問への反応(ブックマークコメント)

質問の情報

登録日時
2009-08-31 16:59:46
終了日時
2009-09-07 17:00:06
回答条件
1人5回まで 150 ptで終了

この質問のカテゴリ

この質問に含まれるキーワード

C++540Canvas45Builder51スレッド378

人気の質問

メニュー

PC版