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