我有一个内存损坏错误(我怀疑),这会导致特定 UI 操作后程序崩溃。这是一个 Cocoa Objective-C 应用程序,不使用 GC。
经过几个小时的调试,我找到了崩溃的可能原因:
DiscSelectPopup *popupSelect = [[DiscSelectPopup alloc] initWithDataList:dataList count:count];
NSInteger result = [NSApp runModalForWindow:popupSelect.window];
上面的弹出例程是从辅助线程执行的。每次用户单击按钮时都会创建并启动该线程。因此,我们可以同时显示多个模式弹出窗口。
当我在 Debug模式下运行程序时 MallocStackLogging=1
和MallocStackLoggingNoCompact=1
,它会在 runModalForWindow:
处打印一条 malloc 错误日志消息。打电话(但不总是)。
malloc: *** error for object 0xbc65840: double free
.....
malloc: *** error for object 0xbc547e0: pointer being freed was not allocated
使用runModalForWindow:
真的很糟糕吗?来自辅助线程?
这可能是崩溃的原因吗?
最佳答案
Is it really bad to use
runModalForWindow
from the secondary thread?
是的。 UI 的事情需要在主线程上发生。
您也不应该使用 runModalForWindow:
,除非您特别想要阻止应用程序中的所有其他窗口(基本上卡住除该窗口之外的应用程序)。只显示窗口。如果您想阻止特定窗口(或者您的应用程序是单窗口),请将其作为工作表开始。
编辑:再次查看问题,这引起了我的注意:
The above popup routine is executed from a secondary thread.
不要那样做。要显示一个窗口,只需显示它即可。从主线程上的按钮接收操作消息,然后在辅助线程上仅执行实际工作(如果有的话)。
请注意,显示该窗口不会阻止任何其他窗口或您正在执行的任何其他操作,除非您特意让它这样做(即使用 runModalForWindow:
)。如果您以正常方式显示窗口,则所有窗口都会继续正常工作。您在主线程上安排的任何计时器和观察者以及类似的事物也将继续工作。您不需要为此创建线程或执行任何其他特殊操作;默认情况下一切都有效。
如果您最终要做的工作可能需要相当长的时间,那么您应该将该放在辅助线程,仅在需要时才执行。您还应该考虑构建为操作对象或 block 是否比构建为原始线程更容易或更好。可能会的。
关于objective-c - 从多个线程使用 runModalForWindow 有多危险?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10318509/