0

特定の UI アクションの後にプログラムがクラッシュする原因となる、メモリ破損エラー (と思われます) があります。これは Cocoa Objective-C アプリケーションであり、GC を使用しません。

何時間ものデバッグの後、クラッシュの考えられる理由を見つけました。

DiscSelectPopup *popupSelect = [[DiscSelectPopup alloc] initWithDataList:dataList count:count];     
NSInteger result = [NSApp runModalForWindow:popupSelect.window];

上記のポップアップ ルーチンは、セカンダリ スレッドから実行されます。このスレッドは、ユーザーがボタンをクリックするたびに作成および開始されます。したがって、複数のモーダルポップアップを同時に表示できます。

と を使用してプログラムをデバッグ モードで実行するMallocStackLogging=1MallocStackLoggingNoCompact=1、呼び出し時に malloc エラー ログ メッセージが出力されrunModalForWindow:ます (常にではありません)。

malloc: *** error for object 0xbc65840: double free
.....
malloc: *** error for object 0xbc547e0: pointer being freed was not allocated

runModalForWindow:セカンダリスレッドから使​​用するのは本当に悪いですか?
それがクラッシュの原因でしょうか?

4

2 に答える 2

6

runModalForWindow二次スレから使って本当にまずいの?

はい。UI の処理はメイン スレッドで行う必要があります。

また、アプリケーション内の他のすべてのウィンドウを特にブロックする必要がない限り、使用しrunModalForWindow:ないでください (基本的に、そのウィンドウを除いてアプリをフリーズします)。ウィンドウを表示するだけです。特定のウィンドウをブロックする場合 (またはアプリが単一ウィンドウの場合) は、シートとして開始します。

編集:質問をもう一度見て、これは私の目を引きました:

上記のポップアップ ルーチンは、セカンダリ スレッドから実行されます。

そうしないでください。ウィンドウを表示するには、表示するだけです。メイン スレッドのボタンからアクション メッセージを受信し、セカンダリ スレッドで実際の作業のみを行います。

ウィンドウを表示しても、他のウィンドウや実行中の操作がブロックされないことに注意してください (つまり、 を使用runModalForWindow:)。通常の方法でウィンドウを表示すると、すべてのウィンドウが正常に動作し続けます。メインスレッドでスケジュールしたタイマーとオブザーバー、および同様のものも引き続き機能します。スレッドを作成したり、このために特別なことをしたりする必要はありません。すべてデフォルトで機能します。

最終的に実行する作業にかなりの時間がかかる可能性がある場合は、それ実行する時が来たときにのみ、それをセカンダリ スレッドに配置する必要があります。また、生のスレッドとして構築するよりも、操作オブジェクトまたはブロックとして構築する方が簡単であるかどうかも検討する必要があります。おそらくそうなるでしょう。

于 2012-04-25T15:49:09.213 に答える
-3

valgrind memcheck を使用して、セカンダリ スレッドのrunModalForWindow:呼び出しがメモリ破損の問題と直接関係していないという結論に達しました。

はい、非メイン スレッドから UI コンポーネントを操作するのは不適切なコーディングですが、そのような動作だけでプログラムがクラッシュすることはありません。

問題の malloc エラー メッセージは、誤って二重に解放されたポップアップ ウィンドウ オブジェクトが原因でした。

ちなみに、メモリ破損の本当の原因は、malloc/free 呼び出しの不一致 (malloc されていないメモリ ポインタの解放) でした。

于 2012-04-26T13:25:17.417 に答える