简体   繁体   中英

Using Apple autorelease pools without Objective-C

I am developing an application that needs to work on Linux, Windows and Mac OS X. To that purpose, I am using C++ with Qt.

For many reasons, on Mac OS X, I need to use CoreFoundation functions (such as CFBundleCopyBundleURL ) that creates core objects that need to be released with CFRelease . But doing so generate a lots of these warnings:

*** __NSAutoreleaseNoPool(): Object 0x224f7e0 of class NSURL autoreleased with no pool in place - just leaking

All the code I've seen concerning these autorelease pools are written in Objective-C. Does anybody know how to create/use autorelease pools in C or C++?

All the code I've seen concerning these autorelease pools are written in Objective-C.

Because autorelease pools only exist in Cocoa and Cocoa Touch.

Does anybody know how to create/use autorelease pools in C or C++?

The only way to do it is to wrap Cocoa code (the creation and drainage of a pool) in a pair of C functions. Even then, that is an ugly hack that merely masks a deeper problem.

What you really should do is find out exactly what is autoreleasing objects (Instruments will help you do this) and either fix it or excise it.

id is a C declaration. You can simply add scope based autorelease pools to your cpp program like so:

autorelease_pool.hpp

class t_autorelease_pool {
public:
    t_autorelease_pool();
    ~t_autorelease_pool();
private:
    id d_pool; // << you may opt to preprocess this out on other platforms.
private:
    t_autorelease_pool(const t_autorelease_pool&);
    t_autorelease_pool& operator=(const t_autorelease_pool&);
};

autorelease_pool.mm

t_autorelease_pool::t_autorelease_pool() : d_pool([NSAutoreleasePool new]) {}
t_autorelease_pool::~t_autorelease_pool() { [this->d_pool drain]; }

In a cpp program:

void UpdateUI() {
    t_autorelease_pool pool;
    // your/their autoreleasing code here
}

An alternative (which can be very easy to use incorrectly) is to use the ObjC runtime directly - which would look like the following C program:

#include <objc/runtime.h>
#include <objc/message.h>
...
id pool = objc_msgSend(objc_getClass("NSAutoreleasePool"), sel_getUid("new")); 
/* do stuff */
objc_msgSend(pool, sel_getUid("drain"));

The error you get is caused by something somewhere creating an Objective-C class (NSURL) using the convenience static method [NSURL urlWithString:]. Methods that return objects that aren't "alloc" or "copy" should put the object inside an autorelease pool before returning the object. And since you haven't setup one up it'll just crash or leak memory.

I'm not sure exactly how to fix this but you need to put something like:

NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
doStuff();
[pool release];

somewhere in your code.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM