内存泄漏-不确定如何/在何处CFRelease()CFSet [英] Memory Leak - Not Sure How/Where to CFRelease() CFSet

查看:233
本文介绍了内存泄漏-不确定如何/在何处CFRelease()CFSet的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我再次遇到内存泄漏的问题,需要一些帮助来解决这一问题.我知道(或很确定)CFSet是这里的问题.

I'm yet again struggling with a memory leak, and need some help figuring this one out. I know (or am pretty sure) the CFSet(s) are the problem here.

我假设我需要CFRelease()它们,但是由于我还需要在USBDeviceCount()中返回CFSet,因此不确定如何完成此操作.任何帮助,将不胜感激!谢谢!

I assume I need to CFRelease() them, but am not sure how to accomplish this since I also need to return a CFSet in USBDeviceCount(). Any help would be appreciated! Thank you!

这是代码(看起来很不错!除了泄漏):

Here's the code (which seemingly works great! except for the leaks):

// 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);

}

为完整起见,这是我在卡尔的帮助下能够实现的解决方案(谢谢卡尔!!):

AppDelegate.h:

AppDelegate.h:

- (void) updateConnectedUSBs;
@property(retain) __attribute__((NSObject)) IOHIDManagerRef hidManager;
@property (strong) NSSet *usbDeviceSet;

AppDelegate.m:

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);

}

推荐答案

在释放集合之前,您需要存储计数. (这是所有NSObject子类通过-release方法在ARC之前工作的方式.)

You need to store the count before releasing the set. (This was the way all NSObject subclasses worked before ARC, via the -release method.)

if (devSet) {
     long count = (long)CFSetGetCount(devSet);
     CFRelease(devSet);
     return count;
}

如果可以使用CFAutorelease()函数,那是创建后可以立即调用的另一种方法,它将在运行循环结束时收集.但是,如果直接使用CFRelease不会增加代码的复杂性,则效率会更高.提早进行自动释放有时可以避免以后再检查是否有多次退货.

If you can use the CFAutorelease() function, that is another way which you could call right after creating it, and it will be collected at the end of the run loop. But using CFRelease directly is a bit more efficient if it doesn't add any complexity to the code. Autoreleasing early can sometimes avoid multiple checks later on if there are multiple returns.

我相信,您还需要CFR释放HIDManager实例.

You also need to CFRelease the HIDManager instance, I believe.

这篇关于内存泄漏-不确定如何/在何处CFRelease()CFSet的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆