我有一个Cocoa插件,它被加载到现有的Carbon应用程序中。
首次加载插件时,Carbon应用程序调用初始化函数Plugin_Init()
,并在该函数中设置环境,如下所示:
//this is the global autorelease pool
static NSAutoreleasePool* globalPool = nil;
void Plugin_Init()
{
NSApplicationLoad(); //loads the Cocoa event loop etc
//create an autorelease pool
globalPool=[[NSAutoreleasePool alloc] init];
//callback functions are registered here
Plugin_defineFunction("doSomething",doSomething,0);
}
但是,Carbon应用程序在应用程序即将终止时不会发送任何通知。
是否真的有必要清理我在应用程序终止时创建的“全局”自动释放池?
我尝试通过添加对下面registerForApplicationQuitNotification()
函数的调用来注册Carbon app quit事件,但是当应用程序终止时,我收到警告,我在无效的自动释放池上调用了-release
。我是如何处理碳事件的?
//handles the Carbon application quit notification
static pascal OSStatus handleApplicationQuitEvent(EventHandlerCallRef nextHandler, EventRef evt, void *ud)
{
OSStatus err = noErr;
UInt32 evtkind;
evtkind = GetEventKind( evt );
if ( evtkind == kEventAppQuit )
{
//release the global autorelease pool
[globalPool release];
}
// call the rest of the handlers
err = CallNextEventHandler( nextHandler, evt);
return err;
}
//registers for the Carbon application quit notification
void registerForApplicationQuitNotification()
{
// install an event handler to tear down some globals on Quit
static EventHandlerUPP app = NULL;
EventTypeSpec list[] = {
{kEventClassApplication, kEventAppQuit},
};
app = NewEventHandlerUPP( handleApplicationQuitEvent );
if (!app)
return;
InstallApplicationEventHandler(app, GetEventTypeCount(list), list, NULL, NULL);
}
答案 0 :(得分:2)
很可能NSApplicationLoad
设置了NSApplication的第一个自动释放池,它将在自动释放池堆栈中低于你自己(因为它是首先创建的)。在后台,它将耗尽这个池并根据需要创建一个新池;这是第一次发生your pool goes away, since it was above Cocoa's pool in the stack。
简单的解决方案是删除全局池,让NSApplication创建它。另一种方法是在每个处理函数中创建和排空本地池,特别是如果您实际上不需要插件中的Application Kit中的任何内容。
答案 1 :(得分:1)
如果自动释放池是您需要进行的唯一清理,那么不,您不需要注册退出通知。您创建的任何池仍然在应用程序的地址空间内,当进程终止时,操作系统将释放该空间。
此外,自动释放池通常是每个线程创建的。如果在不同的线程上调用回调,则可能需要为每个线程创建一个池。请注意,Cocoa也需要被告知它在多线程环境中运行;请参阅NSAutoreleasePool reference。
的“主题”部分