【发布时间】:2023-03-29 13:44:01
【问题描述】:
我再次为内存泄漏而苦苦挣扎,需要一些帮助来解决这个问题。我知道(或很确定)CFSet 是这里的问题。
我假设我需要对它们进行 CFRelease(),但我不确定如何完成此操作,因为我还需要在 USBDeviceCount() 中返回一个 CFSet。任何帮助,将不胜感激!谢谢!
这是代码(看起来效果很好!除了泄漏):
// New USB device has been added (callback function)
static void Handle_DeviceMatchingCallback(void *inContext,
IOReturn inResult,
void *inSender,
IOHIDDeviceRef inIOHIDDeviceRef){
// Log the device ID & device count
NSLog(@"\nNew USB device: %p\nDevice count: %ld",
(void *)inIOHIDDeviceRef,
USBDeviceCount(inSender));
}
// USB device has been removed (callback function)
static void Handle_DeviceRemovalCallback(void *inContext,
IOReturn inResult,
void *inSender,
IOHIDDeviceRef inIOHIDDeviceRef){
// Log the device ID & device count
NSLog(@"\nUSB device removed: %p\nDevice count: %ld",
(void *)inIOHIDDeviceRef,
USBDeviceCount(inSender));
}
// Counts the number of devices in the device set (includes all USB devices that match dictionary)
static long USBDeviceCount(IOHIDManagerRef HIDManager)
{
// The device set includes all USB devices that match our matching dictionary. Fetch it.
CFSetRef devSet = IOHIDManagerCopyDevices(HIDManager);
// The devSet will be NULL if there are 0 devices, so only try to count the devices if devSet exists
if(devSet) return CFSetGetCount(devSet);
// There were no matching devices (devSet was NULL), so return a count of 0
return 0;
}
- (void) applicationDidFinishLaunching:(NSNotification *)aNotification {
// Create an HID Manager
IOHIDManagerRef HIDManager = IOHIDManagerCreate(kCFAllocatorDefault,
kIOHIDOptionsTypeNone);
// Create a Matching Dictionary
CFMutableDictionaryRef matchDict = CFDictionaryCreateMutable(
kCFAllocatorDefault,
2,
&kCFTypeDictionaryKeyCallBacks,
&kCFTypeDictionaryValueCallBacks);
// Specify a device manufacturer in the Matching Dictionary
CFDictionarySetValue(matchDict,
CFSTR(kIOHIDTransportKey),
CFSTR("USB"));
// Register the Matching Dictionary to the HID Manager
IOHIDManagerSetDeviceMatching(HIDManager, matchDict);
// Register a callback for USB device detection with the HID Manager
IOHIDManagerRegisterDeviceMatchingCallback(HIDManager, &Handle_DeviceMatchingCallback, NULL);
// Register a callback fro USB device removal with the HID Manager
IOHIDManagerRegisterDeviceRemovalCallback(HIDManager, &Handle_DeviceRemovalCallback, NULL);
// Register the HID Manager on our app’s run loop
IOHIDManagerScheduleWithRunLoop(HIDManager, CFRunLoopGetMain(), kCFRunLoopDefaultMode);
// Open the HID Manager
IOReturn IOReturn = IOHIDManagerOpen(HIDManager, kIOHIDOptionsTypeNone);
if(IOReturn) NSLog(@"IOHIDManagerOpen failed."); // Couldn't open the HID manager!
CFSetRef devSet = IOHIDManagerCopyDevices(HIDManager);
CFRelease(devSet);
CFRelease(matchDict);
}
为了完整起见,这是我在 Carl 的帮助下能够实施的解决方案(感谢 Carl!):
AppDelegate.h:
- (void) updateConnectedUSBs;
@property(retain) __attribute__((NSObject)) IOHIDManagerRef hidManager;
@property (strong) NSSet *usbDeviceSet;
AppDelegate.m:
// New USB device has been added (callback function)
static void Handle_DeviceMatchingCallback(void *inContext,
IOReturn inResult,
void *inSender,
IOHIDDeviceRef inIOHIDDeviceRef){
AppDelegate *appDelegate = (AppDelegate *)[[NSApplication sharedApplication] delegate];
[appDelegate updateConnectedUSBs];
}
// USB device has been removed (callback function)
static void Handle_DeviceRemovalCallback(void *inContext,
IOReturn inResult,
void *inSender,
IOHIDDeviceRef inIOHIDDeviceRef){
AppDelegate *appDelegate = (AppDelegate *)[[NSApplication sharedApplication] delegate];
[appDelegate updateConnectedUSBs];
}
- (void) updateConnectedUSBs {
CFSetRef devSet = IOHIDManagerCopyDevices(_hidManager);
self.usbDeviceSet = CFBridgingRelease(devSet);
NSLog(@"%@",self.usbDeviceSet);
}
- (void) applicationDidFinishLaunching:(NSNotification *)aNotification
{
_hidManager = IOHIDManagerCreate(kCFAllocatorDefault, kIOHIDOptionsTypeNone);
// Create a Matching Dictionary
CFMutableDictionaryRef matchDict = CFDictionaryCreateMutable(
kCFAllocatorDefault,
2,
&kCFTypeDictionaryKeyCallBacks,
&kCFTypeDictionaryValueCallBacks);
// Specify a device manufacturer in the Matching Dictionary
CFDictionarySetValue(matchDict,
CFSTR(kIOHIDTransportKey),
CFSTR("USB"));
// Register the Matching Dictionary to the HID Manager
IOHIDManagerSetDeviceMatching(_hidManager, matchDict);
// Register a callback for USB device detection with the HID Manager
IOHIDManagerRegisterDeviceMatchingCallback(_hidManager, &Handle_DeviceMatchingCallback, NULL);
// Register a callback fro USB device removal with the HID Manager
IOHIDManagerRegisterDeviceRemovalCallback(_hidManager, &Handle_DeviceRemovalCallback, NULL);
// Register the HID Manager on our app’s run loop
IOHIDManagerScheduleWithRunLoop(_hidManager, CFRunLoopGetMain(), kCFRunLoopDefaultMode);
// Open the HID Manager
IOReturn IOReturn = IOHIDManagerOpen(_hidManager, kIOHIDOptionsTypeNone);
if(IOReturn) NSLog(@"IOHIDManagerOpen failed."); // Couldn't open the HID manager!
CFRelease(matchDict);
}
【问题讨论】:
标签: objective-c memory-leaks usb core-foundation iokit