【问题标题】:How to create a NSAutoreleasePool without Objective-C?如何在没有 Objective-C 的情况下创建 NSAutoreleasePool?
【发布时间】:2012-06-29 13:21:01
【问题描述】:

我有用 C++ 编写的多平台游戏。在 mac 版本中,即使我没有任何 obj-c 代码,但我使用的库之一似乎是自动释放的东西,并且我因此而出现内存泄漏,因为我没有创建 NSAutoreleasePool。

我想要的是能够在不使用 obj-c 代码的情况下创建(和销毁)一个 NSAutoreleasePool,因此我不需要创建一个 .m 文件,并为此更改我的构建脚本。那可能吗?怎么可能?

OBS:标记为 C 和 C++,因为任何这些语言的解决方案都可以。

【问题讨论】:

  • 您的问题是编写任何objective-c 代码吗?或者当您只需要 .c/.cpp 时,您的项目中有 .m 文件?
  • 请注意,虽然@abarnert 的代码是一个可行的解决方案,但这表明库中存在错误。在不生成自动释放池的情况下,任何 C 或 C++ 函数都不应调用 ObjC 代码。如果这是 Apple 代码,您应该在 bugreport.apple.com 上打开雷达。
  • @RobNapier:+1。如果它是第三方库,您应该向库供应商提交错误。许多第三方库(尤其是跨平台库)假设任何 Mac 应用程序都有一个 Cocoa 运行循环和一个活动的 NSAutoreleasePool,即使您只调用 C/C++ 接口,这显然是错误的。他们可能无法或不愿意修复它,但您应该让他们知道。
  • 当然。不过,objc_autoreleaseNoPool 上的断点应该很快就会显示出罪魁祸首。
  • 就个人而言,我发现 CMake 比 objc-runtime 更容易理解。我做过的大多数 CMake 项目都有一个针对每个平台的平台特定目录,以及 CMake 中的几行代码来选择要放入的正确目录(您可以从示例或现有开源项目中复制该目录)。但另一方面,有时在背后玩 ObjC 也很有趣,所以如果你想那样做,那就去做吧。

标签: c++ objective-c c macos


【解决方案1】:

你无法避免实例化 Objective-C 运行时——但显然你已经拥有了其中之一。

如果您想通过 C 与运行时交互,可以使用 Objective-C 运行时 API,如 Objective-C Runtime Programming GuideObjective-C Runtime Reference 中所述。

这个想法是这样的(未经测试):

#include <objc/runtime.h>
#include <objc/objc-runtime.h>
id allocAndInitAutoreleasePool() {
  Class NSAutoreleasePoolClass = objc_getClass("NSAutoreleasePool");
  id pool = class_createInstance(NSAutoreleasePoolClass, 0);
  return objc_msgSend(pool, "init");
}
void drainAutoreleasePool(id pool) {
  (void)objc_msgSend(pool, "drain");
}

如果你想从另一个文件中调用这些函数,当然你也必须在其中包含 objc/runtime.h。或者,或者,您可以在 allocAndInit 函数的返回中将 id 强制转换为 void*,然后在 drain 函数中获取 void* 并强制转换回 id。 (您也可以前向声明 struct objc_object 和 typedef struct objc_object *id,但我相信这实际上并不能保证是正确的定义。)

您不必在链接命令中传递 -lobjc。

不用说,仅仅让构建脚本处理 .m 文件可能会减少工作量。

【讨论】:

  • 您应该能够使用纯 C 代码加载运行时文件(无需 -lobjc)。你可以在这里看到一个例子:github.com/rnapier/ios5ptl/blob/master/ch20/Runtime/MyMsgSend.c(我不建议你使用myMsgSend(),它是其他东西的演示。我只是展示了一个可编译的 C 文件来说明这种方法有效。)跨度>
  • 附带说明,虽然.m 文件可能没问题,但我不建议您使用.mm 文件解决此问题,除非是非常小的包装器。 ObjC++ 会导致很多问题。就像一块胶水一样好,这是解决这个问题的好方法(将调用粘在一个小的.mm 函数中,带有纯C 或C++ 标头和调用周围的@autorelease{})。但请保持您的 C++ 纯正和 ObjC 纯正。
  • @RobNapier:感谢关于 -lobjc 的说明。我会更新答案。
猜你喜欢
  • 1970-01-01
  • 2012-05-20
  • 2010-10-25
  • 1970-01-01
  • 2017-01-15
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-01-18
相关资源
最近更新 更多