Objective c HIDManager Wierd CFRunLoop终止
我已经创建了设备匹配和设备删除回调,并且需要运行CFRunLoop,以便在设备插入和删除时调用这些回调 但问题是,DeviceMatch回调需要花费大量的处理时间,并且取决于要连接的设备,因此我想通过在有限的时间内运行CFRunLoop来检测设备是否被删除,并随之发生设备删除回调 但是,它工作了2次,然后抛出exe\u bad\u访问Objective c HIDManager Wierd CFRunLoop终止,objective-c,macos,device-driver,hid,Objective C,Macos,Device Driver,Hid,我已经创建了设备匹配和设备删除回调,并且需要运行CFRunLoop,以便在设备插入和删除时调用这些回调 但问题是,DeviceMatch回调需要花费大量的处理时间,并且取决于要连接的设备,因此我想通过在有限的时间内运行CFRunLoop来检测设备是否被删除,并随之发生设备删除回调 但是,它工作了2次,然后抛出exe\u bad\u访问 设备添加回调 static void Handle_DeviceMatchingCallback(void* inContext, IOReturn inRes
设备添加回调
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 );
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 );
如何生成
匹配cfdictref
?尽管常规惯例会建议IOHIDManager保留或复制它,但也有可能不是。我现在会尝试取出CFRelease
,看看这是否会改善情况
CFGetTypeID
中的崩溃表示它正试图处理已释放的CF对象。您可以做一些事情来调试它是哪一个:
- 打开。它可能会工作,即使这是一个CF对象(许多CF对象是免费桥接的,并且仍然可以工作)
- 在调试器中,将参数选中为
。有关取决于处理器的正确寄存器,请参阅。(此页面是否用于ObjC并不重要;您只需要与CFGetType
相关的entires)arg0
匹配cfdictref
?尽管常规惯例会建议IOHIDManager保留或复制它,但也有可能不是。我现在会尝试取出CFRelease
,看看这是否会改善情况
CFGetTypeID
中的崩溃表示它正试图处理已释放的CF对象。您可以做一些事情来调试它是哪一个:
- 打开。它可能会工作,即使这是一个CF对象(许多CF对象是免费桥接的,并且仍然可以工作)
- 在调试器中,将参数选中为
。有关取决于处理器的正确寄存器,请参阅。(此页面是否用于ObjC并不重要;您只需要与CFGetType
相关的entires)arg0
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 );
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>
0x00007fff8534407a jne 0x7fff8534409f
0x00007fff8534407c mov 0x18(%rdi),%rdi
0x00007fff85344080 mov(%rdi),%rax
0x00007fff85344083 lea 0x58(%r12),%rsi
0x00007fff85344088 callq*0x40(%rax)
0x00007fff8534408b测试%eax,%eax
0x00007fff8534408d jne 0x7fff85344148
0x00007fff85344093 cmpq$0x0,0x58(%r12)
0x00007fff85344099 je 0x7fff85344148
0x00007fff8534409f mov 0x58(%r12),%rdi
0x00007fff853440a4呼叫0x7fff85368f36
0x00007fff853440a9移动百分比rax,%rbx
0x00007fff853440ac呼叫0x7fff85369008
0x00007fff853440b1 cmp%rax,%rbx
0x00007fff853440b4 jne 0x7fff853440cc
我看到它在0x00007fff85344080 mov(%rdi),%rax处断开,用于IOHIDDeviceScheduleWithRunLoop(请使用0x00007fff85344080搜索)
在参考文档的帮助下,我看到它是第一个参数,表示tIOHIDManagerRef,我创建了IOHIDManagerRef tIOHIDManagerRef=IOHIDManagerCreate(kcfalocatordefault,kIOHIDOptionsTypeNone)
但是,如何从堆栈跟踪上方查看它的地址?下面是生成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 );
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>
0x00007fff8534407a jne 0x7fff8534409f
0x00007fff8534407c mov 0x18(%rdi),%rdi
0x00007fff85344080 mov(%rdi),%rax
0x00007fff85344083 lea 0x58(%r12),%rsi
0x00007fff85344088 callq*0x40(%rax)
0x00007fff8534408b测试%eax,%eax
0x00007fff8534408d jne 0x7fff85344148
0x00007fff85344093 cmpq$0x0,0x58(%r12)
0x00007fff85344099 je 0x7fff85344148
0x00007fff8534409f mov 0x58(%r12),%rdi
0x00007fff853440a4呼叫0x7fff85368f36
0x00007fff853440a9移动百分比rax,%rbx
0x00007fff853440ac呼叫0x7fff85369008
0x00007fff853440b1 cmp%rax,%rbx
0x00007fff853440b4 jne 0x7fff853440cc
我看到它在0x00007fff85344080 mov(%rdi),%rax处断开,用于IOHIDDeviceScheduleWithRunLoop(请使用0x00007fff85344080搜索)
在参考文档的帮助下,我看到它是第一个参数,表示tIOHIDManagerRef,我创建了IOHIDManagerRef tIOHIDManagerRef=IOHIDManagerCreate(kcfalocatordefault,kIOHIDOptionsTypeNone)
但是,如何从堆栈跟踪上方查看它的地址?哪一行生成异常?堆栈是什么?CFRunLoopRun();(我还看到了在堆栈跟踪中CFRunLoop调用CFGetTypeID)堆栈包含第一个代码块的方法,然后是CFRunLoop,然后是CFGetTypeID。哪一行生成了异常?堆栈是什么?CFRunLoopRun();(我还看到了在堆栈跟踪中CFRunLoop调用CFGetTypeID)堆栈包含第一个代码块的方法,然后是CFRunLoop,然后是CFGetTypeID。如果我打开NSZombie,它可以工作,但在控制台中看不到任何日志或在工具中看不到任何消息。因此,这就离开了调试器。检查要传递给CFGetType的对象的地址,并将其与您知道的对象进行比较。请检查我的其他响应。您可以告诉我如何检查堆栈跟踪中的地址吗?堆栈跟踪中没有地址。您需要在调试器中检查它,如上面的“检查gdb中的Obj-C参数”链接中所述。如果我打开NSZombie,它可以工作,但在控制台中看不到任何日志或仪器中没有任何消息。因此,调试器将离开。检查要传递到的对象的地址