我刚刚重新开始 Mac 开发。
我正在使用 CoreMIDI,它是一个 C API,它允许我定义一个 C 回调函数,每当 MIDI 消息到达时,该函数就会在单独的线程上从 MIDI 服务器调用。此回调的注册是在由 awakeFromNib 调用触发的 Objective-C/C 代码中完成的。
它似乎工作正常,除了当我收到第一次回调时,我在控制台上收到以下警告消息:
MidiList(6685,0x103ddb000) malloc: *** auto malloc[6685]: error: GC operation on unregistered thread. Thread registered implicitly. Break on auto_zone_thread_registration_error() to debug.
我在网上阅读了这篇文章,这听起来像是一个无害的错误。但对我来说奇怪的是我不明白“GC操作”是如何发生的?我的项目确实启用了 GC,但我认为这仅适用于 Cocoa 部分。我的回调不使用任何 Cocoa 代码,它只是一个免费函数,它使用一些 CoreMIDI 和 CoreFoundation 功能(包括 CFSTR,如果重要的话)。如果我没有使用任何 Cocoa 对象,为什么该线程上会发生 GC 操作?
最佳答案
因为垃圾收集器不知道您在此线程上没有使用 Cocoa。
Cocoa 提供的垃圾收集器是一个保守的垃圾收集器:它实际上对程序的结构几乎一无所知。它所做的只是扫描每个线程的堆栈和堆上的对象,寻找看起来指针的位模式,如果在这个可能的位置有一个对象,它就会使其保持事件状态。
显然,存在误报的可能性。您可以拥有一个具有类似于指针的值的整数,并且垃圾收集器会认为它是一个。
此外,您可以使用 NSAllocateCollectable
以类似 malloc
的方式分配垃圾回收内存。 GC 也必须考虑到它们,特别是因为返回的指针可能会传递到甚至不知道垃圾回收的 C 代码中。
编辑 除了 NSAllocateCollectable
之外,Core Foundation 对象(CF
前缀类型)可以在 CFMakeCollectable
的帮助下进行垃圾收集。一旦使用,垃圾收集器就会处理它们。
关于objective-c - Core MIDI 回调中未注册线程上的 GC,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3648605/