内存泄漏 - 不确定如何/在何处CFRelease()CFSet

时间:2018-05-13 00:41:57

标签: objective-c memory-leaks usb core-foundation iokit

我又一次在内存泄漏方面苦苦挣扎,需要一些帮助来解决这个问题。我知道(或者很确定)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);

}

leaks

为了完整起见,这是我能够在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);

}

enter image description here

0 个答案:

没有答案