2012-04-25 12 views
0

私は特定のUIアクションの後にプログラムがクラッシュするメモリ破損エラー(私は疑いがあります)があります。これはCocoa Objective-Cアプリケーションであり、GCは使用しません。複数のスレッドからrunModalForWindowを使用するのは危険ですか?

デバッグの多くの時間後、私はクラッシュの可能な理由を見つけました:

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

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

私はMallocStackLogging=1MallocStackLoggingNoCompact=1でデバッグモードでプログラムを実行すると、それはrunModalForWindow:コール(常にではない)でのmallocエラーログメッセージを出力します。

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

セカンダリスレッドからrunModalForWindow:を使用することが本当に悪いですか?
クラッシュの原因になりますか?

答えて

-3

valgrind memcheckを使用して、私は副次的なスレッドrunModalForWindow:コールがメモリ破損の問題に直接接続していないと結論付けました。

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

質問のmallocエラーメッセージは、間違って二重にリリースされたポップアップウィンドウオブジェクトのためです。

ちなみに、メモリ破損の本当の原因は、malloc/free呼び出しのミスマッチ(mallocedメモリポインタを解放しない)でした。

+1

あなたはこの特定のクラッシュの原因について正しいかもしれませんが、セカンダリスレッドからのUI操作の重要性を却下する際に間違いがあります。セカンダリスレッドからUIを変更することで、大きな問題やクラッシュを引き起こすことがあります。 [スレッドセーフティサマリー](https://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/Multithreading/ThreadSafetySummary/ThreadSafetySummary.html)を読んでください。 –

+0

ありがとう!これは本当に有益な文書です。 – 9dan

6

補助スレッドからrunModalForWindowを使用することは本当に悪いですか?

はい。メインスレッドでUIの内容が発生する必要があります。

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

編集:上記のポップアップルーチンがセカンダリスレッドから実行される

:質問で再び見ると、これは私の目を引きました。

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

具体的にそうしない限り(つまり、runModalForWindow:を使用)、ウィンドウを表示しても他のウィンドウやその他のものはブロックされません。通常の方法でウィンドウを表示すると、すべてのウィンドウは正常に動作し続けます。メインのスレッドでスケジュールしたタイマーやオブザーバーなども引き続き動作します。このためにスレッドを作成する必要はありません。すべてデフォルトで動作します。あなたはそれを行うには時間が来たときにのみ、セカンダリスレッドでことを置くべきあなたは最終的に、その後、時間の非自明な量をとることができないでしょう

もし仕事。また、生のスレッドよりも操作オブジェクトまたはブロックとして構築する方が簡単かどうかを調べる必要があります。それはおそらくそうです。

+1

メインスレッドでシリアライズされた特定の順序でUIを処理する必要があり、現在の状態を当然のように引き継いでいます...もし別のスレッドから突っ込んだとしても...しかし、実際には本当に悪いと追跡するのが難しいことが、どこかの道のりで起こります。 –

+0

[performSelectorOnMainThread:withObject:waitUntilDone:](https://developer.apple.com/library/mac/documentation /Cocoa/Reference/Foundation/Classes/nsobject_Class/Reference/Reference.html#//apple_ref/doc/uid/20000050-CJBEHAEF)メソッドを使用して、OPがメインスレッドでメソッドを呼び出す方法を知らない場合に備えて、 –

+1

@RobKeniger:他の場所で(スレッドを手動で作成するか、GCDかNSOperationQueueを使って)実行しない限り、メインスレッド上にあることを言及する価値があります。質問に表示されているコードが別のもの最初の場所のスレッド。 –

関連する問題