GC on unregistered thread in a Core MIDI callback
I am just getting started again with Mac development.
I am using CoreMIDI which is a C API which allows me to define a C callback function to be called from the MIDI server on a separate thread whenever a MIDI message arrives. The registration of this callback is done in Objective-C/C code triggered by an awakeFromNib call.
It seems to work fine, except when I 开发者_如何学Cget my first callback I get the following warning message on the console:
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.
I read up on this online and it sounds like a harmless error. But the weird thing to me is I don't understand how a "GC operation" occurred? My project does have GC enabled, but I thought that was only for the Cocoa parts. And my callback doesn't use any Cocoa code, it is just a free function which uses some CoreMIDI and CoreFoundation functionality (including CFSTR if that matters). Why would a GC operation occur on that thread if i'm not using any Cocoa objects?
Because the garbage collector doesn't know you're not using Cocoa on this thread.
The garbage collector that Cocoa sports is a conservative garbage collector: it actually knows next to nothing about how your program is structured. All it does is scanning the stack of each thread, and objects on the heap, for bit patterns that look like pointers, and if there's an object at this would-be location, it keeps it alive.
There is, obviously, a possibility for false positives. You can have an integer that has a value looking like a pointer and the garbage collector will believe it's one.
Besides, you may allocate garbage-collected memory in a malloc
-like way with NSAllocateCollectable
. The GC must take them into account too, especially since the returned pointer could be passed into C code that's not even aware of garbage collection.
EDIT Aside from NSAllocateCollectable
, Core Foundation objects (CF
-prefixed types) can be made garbage-collected with the help of CFMakeCollectable
. Once it's used, the garbage collector will take care of them.
If you are creating pthread, add this objc_registerThreadWithCollector();
to your pthread.
In case you cannot find a symbol or linking error, use following code,
#include <dlfcn.h>
void (*registerThreadWithCollector_fn)(void);
registerThreadWithCollector_fn = (void(*)(void)) dlsym(RTLD_NEXT, "objc_registerThreadWithCollector");
if (registerThreadWithCollector_fn) {
(*registerThreadWithCollector_fn)();
} else {
// do something else
}
精彩评论