从多个线程使用runModalForWindow有多危险?

时间:2012-04-25 15:10:16

标签: objective-c multithreading macos cocoa modal-dialog

我有内存损坏错误(我怀疑),这导致程序在特定UI操作后崩溃。这是一个Cocoa Objective-C应用程序,不使用GC。

经过数小时的调试后,我发现了崩溃的可能原因:

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:真的很糟糕吗? 这可能是坠机的原因吗?

2 个答案:

答案 0 :(得分:6)

  

从辅助线程使用runModalForWindow真的很糟糕吗?

是。 UI东西需要在主线程上发生。

您也不应该使用runModalForWindow:,除非您特别想要阻止应用程序中的所有其他窗口(基本上冻结您的应用程序除了该窗口)。只需显示窗口。如果要阻止特定窗口(或者您的应用程序是单窗口),请将其作为工作表开始。

编辑:再看一下这个问题,这引起了我的注意:

  

上面的弹出例程是从辅助线程执行的。

不要那样做。要显示一个窗口,只需显示它。从主线程上的按钮接收操作消息,然后只在辅助线程上执行实际工作 - 如果有的话。

请注意,显示窗口不会阻止任何其他窗口或您正在执行的任何其他操作,除非您专门执行此操作(即使用runModalForWindow:)。如果以正常方式显示窗口,则所有窗口都会继续正常工作。您在主线程上安排的任何计时器和观察者以及类似的东西也会继续工作。您不需要为此创建线程或执行任何其他特殊操作;它只是默认工作。

如果你最终会做的工作可能需要花费很多时间,那么你应该把那个放在辅助线程,只有到了时候才能做到。您还应该研究构造操作对象或块是否比原始线程更容易或更好。它可能会。

答案 1 :(得分:-3)

使用valgrind memcheck,我得出结论,辅助线程runModalForWindow:调用与内存损坏问题没有直接关联。

是的,从非主线程操作UI组件是不好的编码,但仅此类行为不会使程序崩溃。

问题中的malloc错误消息是由于错误地双重释放的弹出窗口对象造成的。

顺便说一句,内存损坏的真正原因是不匹配的malloc / free调用(释放没有malloced内存指针)。