9da*_*dan 0 macos cocoa multithreading modal-dialog objective-c
我有一个内存损坏错误(我怀疑),这导致程序在特定UI操作后崩溃.这是一个Cocoa Objective-C应用程序,不使用GC.
经过几个小时的调试,我发现了崩溃的可能原因:
DiscSelectPopup *popupSelect = [[DiscSelectPopup alloc] initWithDataList:dataList count:count];
NSInteger result = [NSApp runModalForWindow:popupSelect.window];
Run Code Online (Sandbox Code Playgroud)
上面的弹出例程是从辅助线程执行的.每次用户单击按钮时,都会创建并启动此线程.因此,我们可以同时显示几个模态弹出窗口.
当我使用MallocStackLogging=1和在调试模式下运行程序时MallocStackLoggingNoCompact=1,它会在runModalForWindow:调用时打印malloc错误日志消息(但并非总是如此).
malloc: *** error for object 0xbc65840: double free
.....
malloc: *** error for object 0xbc547e0: pointer being freed was not allocated
Run Code Online (Sandbox Code Playgroud)
runModalForWindow:从辅助线程使用真的很糟糕吗?
这可能是坠机的原因吗?
runModalForWindow从次要线程使用真的很糟糕吗?
是.UI东西需要在主线程上发生.
您也不应该使用,runModalForWindow:除非您特别想要阻止应用程序中的所有其他窗口(基本上冻结您的应用程序除了该窗口).只需显示窗口.如果要阻止特定窗口(或者您的应用程序是单窗口),请将其作为工作表开始.
编辑:再看一下这个问题,这引起了我的注意:
上面的弹出例程是从辅助线程执行的.
不要那样做.要显示一个窗口,只需显示它.从主线程上的按钮接收操作消息,然后仅在辅助线程上执行实际工作(如果有的话).
请注意,显示窗口不会阻止任何其他窗口或您正在做的任何其他操作,除非您特别指示(即使用runModalForWindow:).如果以正常方式显示窗口,则所有窗口都将继续正常工作.您在主线程上安排的任何计时器和观察者以及类似的东西也会继续工作.您不需要为此创建线程或执行任何其他特殊操作; 一切都只是默认工作.
如果你最终要完成的工作可能需要花费很多时间,那么你应该把它放在一个辅助线程上,只有在需要时才进行.您还应该研究构造操作对象或块是否比原始线程更容易或更好.它可能会.