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

Objective c 内存泄漏-不确定如何/在何处释放CFRelease()CFSet,objective-c,memory-leaks,usb,core-foundation,iokit,Objective C,Memory Leaks,Usb,Core Foundation,Iokit,我再次与内存泄漏作斗争,需要一些帮助来解决这个问题。我知道(或相当肯定)CFSet是这里的问题 我假设我需要CFRelease()来释放它们,但我不确定如何实现这一点,因为我还需要在USBDeviceCount()中返回一个CFSet。任何帮助都将不胜感激!谢谢大家! 下面是代码(除了泄漏之外,它似乎工作得很好): 为了完整起见,以下是我在卡尔的帮助下实现的解决方案(谢谢,卡尔!!): AppDelegate.h: - (void) updateConnectedUSBs; @property

我再次与内存泄漏作斗争,需要一些帮助来解决这个问题。我知道(或相当肯定)CFSet是这里的问题

我假设我需要CFRelease()来释放它们,但我不确定如何实现这一点,因为我还需要在USBDeviceCount()中返回一个CFSet。任何帮助都将不胜感激!谢谢大家!

下面是代码(除了泄漏之外,它似乎工作得很好):

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

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

}

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

如果您可以使用CFAutorelease()函数,那么这是您可以在创建它之后立即调用的另一种方法,它将在运行循环结束时被收集。但是如果不增加代码的复杂性,那么直接使用CFRelease会更有效率。如果有多个返回,那么早期自动恢复有时可以避免以后的多次检查


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

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

如果您可以使用CFAutorelease()函数,那么这是您可以在创建它之后立即调用的另一种方法,它将在运行循环结束时被收集。但是如果不增加代码的复杂性,那么直接使用CFRelease会更有效率。如果有多个返回,那么早期自动恢复有时可以避免以后的多次检查


我相信您还需要发布HIDManager实例。

Carl-非常感谢您的回复和解释。你的建议确实大大减少了泄漏物品的数量。我最初尝试过做
CFRelease(HIDManager)
ApplicationIDFinishLaunching
的末尾,但释放HIDManager会导致回调函数从未运行。当我释放HIDManager时,所有的内存泄漏都会停止。如何释放HIDManager,但在连接到Mac的USB设备的#更改时保持回调?这里的目标是在连接/断开USB设备时执行操作。@x74353-啊,是的,如果你需要在应用程序的生命周期内保持HIDManager,泄漏也没什么大不了的。通常的方法是在app委托本身的属性/实例变量中保留一个引用,这将保留它作为属性,然后在其dealloc方法中释放(在正常情况下当然永远不会出现)。设置属性后,可以释放本地引用。这样,如果您曾经运行过clang analyzer(Xcode菜单中的Product->Analyze),就会避免出现警告,它通常会像这样标记泄漏的实例。再次感谢你,卡尔!我已经将你的答案标记为解决方案,并用新代码更新了原始帖子,包含了你的答案和建议。卡尔-非常感谢你的回复和解释。你的建议确实大大减少了泄漏物品的数量。我最初尝试过做
CFRelease(HIDManager)
ApplicationIDFinishLaunching
的末尾,但释放HIDManager会导致回调函数从未运行。当我释放HIDManager时,所有的内存泄漏都会停止。如何释放HIDManager,但在连接到Mac的USB设备的#更改时保持回调?这里的目标是在连接/断开USB设备时执行操作。@x74353-啊,是的,如果你需要在应用程序的生命周期内保持HIDManager,泄漏也没什么大不了的。通常的方法是在app委托本身的属性/实例变量中保留一个引用,这将保留它作为属性,然后在其dealloc方法中释放(在正常情况下当然永远不会出现)。设置属性后,可以释放本地引用。这样,如果您曾经运行过clang analyzer(Xcode菜单中的Product->Analyze),就会避免出现警告,它通常会像这样标记泄漏的实例。再次感谢你,卡尔!我已经将您的答案标记为解决方案,并用新代码更新了原始帖子,其中包含了您的答案和建议。
// 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);

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