3

C++ Builder 6 で作成されたアプリケーションに問題があります。しばらく (週、月) 実行した後、アプリケーションがクラッシュし、エラー メッセージが表示されずに閉じます。クラッシュの直前にアプリケーション ログに、多くの「メモリ不足」の例外が記録されます。メモリ不足の例外をスローしているプロセスを調べたところ (下のスクリーンショット)、コミットされていないプライベート メモリ スペースがたくさんあります。そのような行動の理由は何ですか?

私は数年前に一度、そのような問題を抱えていました。その理由は、リンカーオプションでチェックされていない「動的ライブラリを使用する」オプションでした。もう一度確認すると、問題は解消され、その逆も同様でした。私が作成したテストアプリケーションは、「new char[1000000]」を呼び出してから削除するだけでした。メモリは毎回解放されましたが (Windows タスク マネージャーでコミットされたメモリの増加はありませんでした)、しばらくしてメモリ不足になった後、VMMap はまったく同じことを示しました。多くのプライベート メモリが予約されていますが、そのほとんどはコミットされていません。

問題は再発しましたが、同じ方法で修正することはできません。それが理由かどうかはわかりませんが、同じマシンに Builder 6 と 2010 をインストールしました。今は Builder 6 しか持っていませんが、以前のようにテスト アプリケーションでエラーを再現できないようです。どうやら、メモリマネージャのエラーか何かがあるようです。CodeGuard はメモリ リークを示しません。「新規」でメモリブロックを作成すると「メモリコミットサイズ」に即座に表示され、削除するとメモリ使用量が減少するため、メモリリークはそうではないと仮定すると、タスクマネージャーは「メモリコミットサイズ」をあまり表示しません.

何か私にできることはありますか?コミットされていないメモリを解放する方法はありますか? 問題をさらに診断する方法は?

スクリーンショット: http://i.stack.imgur.com/UKuTZ.jpg

4

2 に答える 2

3

I found a way to simulate this problem and solution.

for(int i=0; i<100; i++)
{
    char * b = new char[100000000];
    new char;
    delete b;
}

Borland memory manager reserves a block of memory which size is multiple of one page which is 4kB. When allocating memory size different than multiple of 4kB there is some free space which borland may use to allocate some other memory chunk. When the first chunk is deallocated the second is still keeping hole memory block reserved.

At first look the code should cause just 100B memory leak, but in fact it will cause memory allocation exception after less than 16 iterations.

I have found two solutions for this problem. One is FastMM, it works but also brings some troubles with it too. Second solution is to exchange borlndmm.dll with the one from Embarcadero Rad Studio 2010. I didn't test it thoroughly yet but it seems to work without any problem.

I should move the hole project to RAD 2010 but for some reasons I got stuck in Borland 6.

于 2013-03-13T11:54:10.330 に答える
0

プロローグ

うーん、興味深い動作...苦労して学んだことを追加する必要があります。BCB6は私の好みに合わないバグが多すぎたので、数回試した直後に却下しました ( BCB5と比較して、特にAnsiStrings の処理に関して)。それで問題なくBCB5を長く使っていました。CAD/CAMのような非常に大きなプロジェクトでも使用しました。

数年後、私は雇用主のためにBDS2006に移動しなければならず、問題が発生しました (いくつかはあなたのものに似ている可能性があります)。マイナーな IDE とトレース/ブレークポイント/コードガードのバグの他に、次のような重要なバグがあります。

  1. メモリマネージャー

    • delete/delete[]通知する例外をスローせずに同じポインターに対して2回呼び出されると、メモリマネージャーが破損します...
    • コンパイラのバグの間違ったデフォルトのコンストラクタ/デストラクタstruct、私が抱えていた最大の問題でした (と組み合わせてdelete)
    • クラスのメンバー関数が間違っているか欠落していると、複数のdelete呼び出しが発生する可能性があります!!! コンパイラまたは C++ エンジンのバグによるものです。

    しかし、私は幸運で、ここで解決しました: bds 2006 C hidden memory manager conflicts (class new / delete[] vs. AnsiString)

  2. 間違ったコンパイル

    アプリが正しくコンパイルされない場合があります。エラーはスローされませんが、一部のコード行が exe にないか、ソース コードとは順序が異なります。これはBCB 5,6でも時々見ました。それを解決するには:

    1. 次のようなすべての一時ファイルを削除します~,obj,tds,map,exe,...
    2. IDE を閉じて、念のために再度開きます (ローカル変数 (ほとんどが大きな配列) のビューが IDE メモリを破損することがあります)。
    3. 再コンパイル
  3. ブレークポイント/トレース/コードガードは生のアプリとは異なる動作をすることに注意してください

    特にマルチスレッド アプリでは、トレース中とそうでない場合で動作が異なります。また、 codeguardは大きな違いをもたらします (これは、機密性の高いタイミングを損なう実行速度の低下を意味するものではありません)。たとえば、コードガードには、理由もなくメモリ例外をスローするという厄介な習慣があるため、メモリ使用量がまだ同じでメモリから遠く離れている場合でも、コードの一部を何度もチェックする必要があります。

  4. AnsiStringオペレーター

    AnsiStringVCL には法線プロパティとコンポーネント プロパティの 2 種類があります。AnsiStringしたがって、コンポーネントのプロパティでは演算子の操作が異なるため、それを考慮するのが賢明です。たとえば、次のようなものを試してください

    Edit1->Text+="xxx";
    

    AnsiStringまた、次のようなオペレーターのバグがまだあります。

    AnsiString version="aaa"+AnsiString("aaa")+"aaa";       // codeguard: array access violation
    
  5. 古い BCB プロジェクトをインポートする

    可能であれば、直接インポートを避けてください。不明な割り当てや memleaks エラーが発生することがよくあります。理由はわかりませんが、インポートされたウィンドウ クラスの処理が異なり、memleaks が箇条書き#1に関連していると思われます。より良い方法は、新しいアプリを作成し、コンポーネントとコードを手動で作成/コピーすることです。バックワードであることはわかっていますが、問題を回避する唯一の安全な方法はまだ問題がどこにあるのかわかりませんが、単純な *.bdsproj の置き換えでは役に立ちません!!! そして、*.dfm には疑わしいものは何もありませんでした。

于 2014-03-04T10:05:18.090 に答える