2013-11-20 4 views
6

大きなデータセットで一度に数日間動作する大規模なMacアプリケーションがあります。 Objective-C++とC++の組み合わせです。マウンテンライオンでは素晴らしい走りを見せていますが、マーベリックスでは約10〜20分(数百万のオブジェクトが割り当てられて破壊されています)に走った後、クラッシュします。無効なポインタ(つまり、削除されたC++オブジェクトで関数を呼び出す)でクラッシュするかのように動作しますが、ポインタが指しているオブジェクトは意味をなさない状態にあります。マーベリックスでNonsensical C++とObjective-C++がクラッシュする

すべての私のC++クラスは、コンストラクタは次のようになり、共通の基本クラスから継承:

MyClass::MyClass() 
{ 
    mCreated = 12345; //int member variable set here and NEVER TOUCHED AGAIN. 
    //other initialization stuff 
} 

それがクラッシュすると、デバッガは悪い物では、mCreatedの値が0であることを示していることがありますオブジェクトがコンストラクタを実行したことがないかのように動作します。

この値は0またはその期待値以外のものではないため、オブジェクトの他のフィールドの値はメモリのストンプミングで予想されるガベージのような値を持たないため、メモリがストンプしているとは思わない。

私はまた、不透明度をオンにして試してみましたが、0x5550xaaaの値はどこにも表示されません。私もGuard Edgeを試しました。

詳細な調査では何も明らかにされていません。悪いオブジェクトは常に同じクラスではありません。私が考えることができるのは、マーベリックス(未使用のメモリを圧縮する)の新しいメモリを持つものが何らかの新しい動作を引き起こしているということです(バグか、以前は不明だった、

誰も似たような人はいますか?あるいは、マーベリックスの下でより強く適用される、ほとんど知られていないメモリルールを知っている人はいますか?

+0

最近、非常に便利な**デバッグテクニックが学びました。(GDB(と確かにLLDB)が読み書き中のメモリアドレスを見ることができます)。私は正確なコマンドを覚えていませんが、確かに "gdb watch memory access"を探してください。 –

+1

aw待ち、いいえ、[ここにあります](http:// stackoverflow。com/questions/58851/can-i-set-a-breakpoint-on-memory-access-in-gdb/59146#59146)。 –

+0

@ H2CO3 - 知っておいてよかったですが、どんなアドレスが詰まるのか分かりません。 –

答えて

4

あなたは無効なポインタ疑惑について正しいと思います。それは削除されたオブジェクトへのポインタかもしれないし、ガベージポインタかもしれない。いずれか1つはmCreatedメンバーと期待通り異なるメンバーと一致します。削除されたオブジェクトの場合、メモリは何か他のものに使用される可能性があり、したがって他の値に設定される可能性があります。ガベージポインターの場合は、クラスのインスタンスであったものを指しているわけではありません。

C++オブジェクトでAllocationsの計測器がどれくらいうまく動作するのかよく分かりませんが、その下でクラッシュを再現することができます。デバッガで停止したら、thisポインタを取得し、そのアドレスの履歴をInstrumentsから取得します。

Instrumentsが動作しない場合は、MallocStackLoggingNoCompact環境変数を設定できます。それは、デバッガで停止したときに、thisポインタを調べ、そのアドレスの履歴を表示するには、次のコマンドを使用します。

(lldb) script import lldb.macosx.heap 
(lldb) malloc_info --stack-history 0x10010d680 

(当然の代わりに0x10010d680thisアドレスを、使用してください。)

あるいは、シェルからmalloc_historyコマンドを使用して、履歴を調査することができます。LLDB内でそれを行うのが面倒な場合は、ヒストリを調べることができます。

+0

このオプションを試して、停止しているアドレスでmalloc_infoを呼び出しました。それは全く何も戻さなかった。私は正しい住所を与えられたことを確認しました。私は、有効な状態にあったスタック内の別のオブジェクトのアドレスでそれを試してみました。そして、mallocについての行を印刷してから、クラスのフルネームについての行を印刷し、次に "エラー:式が失敗しました" 'typedef int kern_return_t;で始まる。 typedef unsigned task_t; #define MAX_FRAMES 128'などヘッダファイルの一部のように見えます。 –

+0

"malloc_history"ツールを使用してみてください。私はLLDBコマンドを知っていますが、経験はありません。それには限界があるかもしれません。あなたが得た結果は、 'this'ポインタが迷惑であることを示唆しています。スタックを上って、呼び出し元が呼び出し元メンバ関数のインスタンスポインタをどこに持っているのかを調べてみてください。おそらく、それは割り当て解除されたインスタンスのメンバ変数などから取得されています。どこかで、ジャンクのチェーンが始まります。 –

関連する問題