2012-04-25 34 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調用(釋放不匹配的內存指針)。

+1

您可能對此特定崩潰的來源是正確的,但在解除輔助線程對UI操作的嚴重性時,您絕對不正確。你可以*通過從輔助線程修改UI來引起重大問題甚至崩潰。您應該閱讀[線程安全摘要](https://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/Multithreading/ThreadSafetySummary/ThreadSafetySummary.html)。 – 2012-04-27 07:21:16

+0

謝謝!這是一個非常有用的文件。 – 9dan 2012-04-27 10:34:06

6

從輔助線程使用runModalForWindow真的不好嗎?

是的。 UI的東西需要在主線程上發生。

你也不應該使用runModalForWindow:,除非你特別想阻止你的應用程序中的所有其他窗口(實質上是凍結你的應用程序,除了那個窗口)。只要顯示窗口。如果你想阻止一個特定的窗口(或你的應用程序是單窗口),請將其作爲工作表開始。

編輯:在這個問題再次查看,這引起了我的眼睛:

上方的彈出式程序從輔助線程執行。

不這樣做。要顯示一個窗口,只需顯示它。從主線程上的按鈕接收動作消息,然後僅在輔助線程上執行實際的工作(如果有的話)。

請注意,顯示窗口不會阻止任何其他窗口或您正在做的任何其他事情,除非您專門做了這些操作(即使用runModalForWindow:)。如果以正常方式顯示窗口,則所有窗口都可以繼續正常工作。您在主線程中安排的任何定時器和觀察者以及類似的東西也會繼續工作。你不需要創建線程或做任何特別的事情;這一切只是在默認情況下工作。

如果那你最終也可能需要一段不平凡的量,然後應該把上輔助線程,只有當它的時間做到這一點的工作。您還應該考慮構建操作對象還是塊比原始線程更簡單還是更好。它可能會。

+1

用戶界面的東西必須按照一定的順序進行,並在主線程中進行序列化,並且理所當然地認爲它的當前狀態......所以如果您從另一個線程中捅過......也許沒有什麼不好的事情發生......但通常情況很糟糕,難以追蹤的地方發生在某處... – 2012-04-25 22:54:56

+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不知道如何調用主線程上的方法。 – 2012-04-26 00:25:48

+1

@RobKeniger:在這種情況下,值得一提的是東西在主線程上,除非在別處執行(無論是通過手動創建線程還是使用GCD或NSOperationQueue),並質疑問題中顯示的代碼是否應該在另一個上線程在第一位。 – 2012-04-26 00:46:12