在没有 Objective-C 的情况下使用 Apple 自动释放池

Posted

技术标签:

【中文标题】在没有 Objective-C 的情况下使用 Apple 自动释放池【英文标题】:Using Apple autorelease pools without Objective-C 【发布时间】:2010-04-01 01:09:01 【问题描述】:

我正在开发一个需要在 Linux、Windows 和 Mac OS X 上运行的应用程序。为此,我将 C++ 与 Qt 结合使用。

出于多种原因,在 Mac OS X 上,我需要使用 CoreFoundation 函数(例如 CFBundleCopyBundleURL)来创建需要使用 CFRelease 发布的核心对象。但是这样做会产生很多这样的警告:

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

我看到的所有关于这些自动释放池的代码都是用 Objective-C 编写的。有人知道如何在 C 或 C++ 中创建/使用自动释放池吗?

【问题讨论】:

这有点奇怪;只要您只使用 CoreFoundation 对象和函数,那不应该发生 - 您能提供更多上下文吗?快速回答一下,不,CoreFoundation 没有自动释放池。 mmmhhh ...你可能是对的。似乎警告不是在调用我的函数时出现,而是在使用 Qt 时出现。 ***.com/questions/865269/… 的副本? 【参考方案1】:

见http://www.codeproject.com/KB/cpp/memreleasepool.aspx

【讨论】:

对不起,我以前没有看过这个帖子。但是,虽然这是一本有趣的读物,但它并没有真正回答我的问题。【参考方案2】:

id 是一个 C 声明。您可以像这样简单地将基于范围的自动释放池添加到您的 cpp 程序中:

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]; 

在 cpp 程序中:

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


另一种方法(可能很容易误用)是直接使用 ObjC 运行时 - 类似于以下 C 程序:

#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"));

【讨论】:

我明白了,所以我真的必须为此使用 Objective-C。谢谢。 @PierreBdR 不,您不必必须。请参阅 C 中替代方案的更新。类型安全/SBRM/编译防火墙 C++ 抽象对大多数人来说更好。【参考方案3】:

我看到的所有关于这些自动释放池的代码都是用 Objective-C 编写的。

因为自动释放池只存在于 Cocoa 和 Cocoa Touch 中。

有人知道如何在 C 或 C++ 中创建/使用自动释放池吗?

唯一的方法是将 Cocoa 代码(池的创建和排放)包装在一对 C 函数中。即便如此,这也是一个丑陋的 hack,只是掩盖了一个更深层次的问题。

您真正应该做的是准确找出什么是自动释放对象(仪器会帮助您做到这一点),然后修复或删除它。

【讨论】:

我看了Instruments,它看起来又大又复杂。你能帮我至少从哪里开始使用它来解决这个问题吗? 其实,为此,在调试器中运行并在__NSAutoreleaseNoPool上中断会更容易。【参考方案4】:

您得到的错误是由于某处使用便利的静态方法 [NSURL urlWithString:] 创建了一个 Objective-C 类 (NSURL) 造成的。返回非“alloc”或“copy”对象的方法应在返回对象之前将对象放入自动释放池中。而且由于您还没有设置它,它只会崩溃或泄漏内存。

我不确定如何解决此问题,但您需要输入以下内容:

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

在你的代码中。

【讨论】:

我确信如果我使用的是 Objective C,这段代码会有所帮助,但正如我在问题中所说,它没有。这就是 pb 的核心:为什么我在使用 C++ 编码时会出现 Objective C 特定的错误?

以上是关于在没有 Objective-C 的情况下使用 Apple 自动释放池的主要内容,如果未能解决你的问题,请参考以下文章

在没有第二个线程的情况下调用objective-c中延迟的函数

iOS 11 中的 SafeArea:如何在没有安全区域的情况下使用自定义导航栏在主屏幕上添加来自 Objective-c 代码的视图

在没有 MonoTouch 托管类的情况下获取 Objective-C 类名

Objective-C/CocoaHTTPServer - 是不是可以在没有任何 UI 的情况下将 CocoaHTTPServer 作为后台应用程序运行?

在没有回调的情况下将选择器分配给Objective-C中的C函数

socket在系统休眠情况下调研转