10

今日、かなり興味深い exc_bad_access クラッシュが発生しました。たくさん掘り下げた後、次の情報を思いつきました(シミュレーターで実行):

コードを実行しただけでは、管理対象オブジェクトにデータをロードしているときに、アプリがランダムな時点でランダムにクラッシュします。私が知る限り、管理対象オブジェクトにデータをロードすると、常にクラッシュしていました。JSON dict からデータ、実際に使用されるオブジェクト (文字列と NSNull から ints/floats と nils へ) に変換されたセクションではありません。

もちろん、ランダムなクラッシュは悪いことなので、デバッガーでプロセスをステップ実行しようとしましたが、実用的ではありませんでした。多くのオブジェクトを処理していたので、それらを 1 つずつステップ実行してもうまくいきませんでした。動作しません。そこで、NSLog をいくつか追加してプロセスを追跡し、その方法でパターンを特定することにしました。

クラッシュを即座に解決しました。

プロセスの任意の場所で 1 つの NSLog がクラッシュを防止しました。

最終的にスタック トレースを追跡したところ、実際の問題が見つかりました。スレッド化された環境でマネージド オブジェクトにアクセスしていましたが、関連する MOC の performBlockAndWait: メソッド内からではありませんでした。その時点で、クラッシュは私には信じられないほど明らかでした。以前は問題が発生していなかったことにショックを受けました。2 ~ 3 個のオブジェクトからなる「小さな」テスト データ セットと、そこに NSLogs を使用したデバッグ コードを用意することで、以前はエラーがかなり効果的にマスクされていたと確信していますが、疑問は残ります。

NSLog によってアプリのクラッシュが防止されるのはなぜですか? 副作用のないコードが、アプリの残りの部分の実行をどのように変更するのでしょうか? これは意味がありません!

4

2 に答える 2

13

驚くべきことに、これはかなり一般的な状況です。一見関係のない場所でログを有効にすると、タイミングの問題が別の場所で即座に解決されるという状況を何度も見てきました。

この理由は、NSLog他の多くの出力関数と同様に、内部同期があるためです。の内部バッファへのアクセスを保護するミューテックスがどこかNSLogにあり、NSLogそれ自体またはそれが使用する I/O ライブラリの 1 つにあります。この同期により、呼び出し元NSLogは複数のスレッドから使​​用できるようになります。プログラムのタイミングを変更し、競合状態に影響を与え、最終的にクラッシュを解決するのは、この同期です。

于 2013-04-10T18:53:58.637 に答える
3

NSLog によってアプリのクラッシュが防止されるのはなぜですか? 副作用のないコードが、アプリの残りの部分の実行をどのように変更するのでしょうか? これは意味がありません!

確かにこれは理にかなっています。本当。

コンソールに何かを出力するための単一のNSLog力は、数秒かかり、いくつかのスレッドでの処理が終了してクラッシュするまでの間に (入力が利用できないことが原因である可能性があります) なくなります。

エラーは非同期呼び出しが原因である可能性があります。次のプロセスは、前のプロセスが完了する前に開始されます。そして、次のプロセスには、前のプロセスからのデータが必要です。NSLog時間を消費します。

于 2013-04-10T18:53:18.577 に答える