我已经创建了设备匹配和设备移除回调,并且需要运行CFRunLoop来在设备插入和移除时调用这些回调。
但问题是,DeviceMatching回调需要大量的处理时间,并且依赖于要附加的设备,所以我希望通过运行CFRunLoop一段有限的时间来检测设备是否被移除,并且设备移除回调也随之发生。
但是,它工作了2次,然后抛出了exe_bad_access。
IOHIDManagerSetDeviceMatching( tIOHIDManagerRef, matchingCFDictRef );
if( matchingCFDictRef ) {
CFRelease( matchingCFDictRef );
}
IOHIDManagerRegisterDeviceMatchingCallback(tIOHIDManagerRef,
Handle_DeviceMatchingCallback,NULL);
IOHIDManagerRegisterDeviceRemovalCallback(tIOHIDManagerRef, Handle_RemovalCallback, NULL);
IOHIDManagerScheduleWithRunLoop(tIOHIDManagerRef, CFRunLoopGetCurrent(), kCFRunLoopDefaultMode);
CFRunLoopRun();设备添加回调
static void Handle_DeviceMatchingCallback(void* inContext, IOReturn inResult,
void* inSender, IOHIDDeviceRef inIOHIDDeviceRef) {
//DO SOME HEAVY PROCESSING
//NOW WE NEED TO CHECK IF DEVICE IS STILL CONNECTED
[[NSRunLoop currentRunLoop] runUntilDate:[NSDate dateWithTimeIntervalSinceNow:1]];
//DO POST PROCESSING
}设备移除回调:
static void Handle_RemovalCallback( void* inContext,IOReturn inResult,
void* inSender, IOHIDDeviceRef inIOHIDDeviceRef) {
//NOW THIS GET's INVOKED, after keeping in run loop
}以下是生成matchingCFDictRef的代码
CFMutableDictionaryRef matchDict = CFDictionaryCreateMutable(kCFAllocatorDefault, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
CFNumberRef vendorIDCFNumRef = CFNumberCreate( kCFAllocatorDefault, kCFNumberIntType, &vendorId );
CFNumberRef productIDCFNumRef = CFNumberCreate( kCFAllocatorDefault, kCFNumberIntType, &productId );
CFDictionarySetValue( matchDict, CFSTR( kIOHIDVendorIDKey ), vendorIDCFNumRef );
CFDictionarySetValue( matchDict, CFSTR( kIOHIDProductIDKey ), productIDCFNumRef );
CFRelease( vendorIDCFNumRef );
CFRelease( productIDCFNumRef );发布于 2012-02-07 23:49:59
如何生成matchingCFDictRef?虽然正常的约定建议IOHIDManager应该保留或复制它,但也有可能不是这样,我现在试着去掉CFRelease,看看这样做是否会有所改善。
CFGetTypeID中的崩溃表明它正在尝试使用已释放的CF对象。您可以做一些事情来尝试调试它是哪一个:
CFGetType。请参阅Inspecting Obj-C parameters in gdb,了解取决于您的处理器的正确寄存器。(这个页面是用于ObjC的并不重要;您只需要与arg0.)相关的所有内容
发布于 2012-02-08 01:32:16
以下是生成matchingCFDictRef的代码
CFMutableDictionaryRef matchDict = CFDictionaryCreateMutable(kCFAllocatorDefault, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
CFNumberRef vendorIDCFNumRef = CFNumberCreate( kCFAllocatorDefault, kCFNumberIntType, &vendorId );
CFNumberRef productIDCFNumRef = CFNumberCreate( kCFAllocatorDefault, kCFNumberIntType, &productId );
CFDictionarySetValue( matchDict, CFSTR( kIOHIDVendorIDKey ), vendorIDCFNumRef );
CFDictionarySetValue( matchDict, CFSTR( kIOHIDProductIDKey ), productIDCFNumRef );
CFRelease( vendorIDCFNumRef );
CFRelease( productIDCFNumRef );现在,我看到了从CFRunLoop调用的不同堆栈跟踪,尽管我仍然在符号中看到了GetTypeID
0x00007fff8534407a <+0023> jne 0x7fff8534409f <IOHIDDeviceScheduleWithRunLoop+60>
0x00007fff8534407c <+0025> mov 0x18(%rdi),%rdi
0x00007fff85344080 <+0029> mov (%rdi),%rax
0x00007fff85344083 <+0032> lea 0x58(%r12),%rsi
0x00007fff85344088 <+0037> callq *0x40(%rax)
0x00007fff8534408b <+0040> test %eax,%eax
0x00007fff8534408d <+0042> jne 0x7fff85344148 <IOHIDDeviceScheduleWithRunLoop+229>
0x00007fff85344093 <+0048> cmpq $0x0,0x58(%r12)
0x00007fff85344099 <+0054> je 0x7fff85344148 <IOHIDDeviceScheduleWithRunLoop+229>
0x00007fff8534409f <+0060> mov 0x58(%r12),%rdi
0x00007fff853440a4 <+0065> callq 0x7fff85368f36 <dyld_stub_CFGetTypeID>
0x00007fff853440a9 <+0070> mov %rax,%rbx
0x00007fff853440ac <+0073> callq 0x7fff85369008 <dyld_stub_CFRunLoopSourceGetTypeID>
0x00007fff853440b1 <+0078> cmp %rax,%rbx
0x00007fff853440b4 <+0081> jne 0x7fff853440cc <IOHIDDeviceScheduleWithRunLoop+105>我看到它在IOHIDDeviceScheduleWithRunLoop的0x00007fff85344080 <+0029> mov (%rdi),%rax处中断(请使用0x00007fff85344080搜索)
在参考文档的帮助下,我看到它是第一个参数,意思是tIOHIDManagerRef,我创建了IOHIDManagerRef tIOHIDManagerRef = IOHIDManagerCreate( kCFAllocatorDefault,kIOHIDOptionsTypeNone );
但是,如何从上面的堆栈跟踪中查看它的地址呢?
https://stackoverflow.com/questions/9168936
复制相似问题