I've got a c++ function that gets a std::map
object and convert it to CFMutableDisctionryRef
in order to use it on method CFNotificationCenterPostNotification
. Here's my implementation :
void IPCNotificationSender::send(const char *identifier, map<const char *, const char *> dict)
{
NSMutableDictionary *myDict = [NSMutableDictionary dictionary];
CFStringRef cfIdentifier = CFStringCreateWithCString(NULL, identifier,
kCFStringEncodingMacRoman);
for (std::map<const char *, const char *>::iterator it=dict.begin(); it!=dict.end(); ++it)
{
NSString *key = [NSString stringWithUTF8String:it->first];
NSString *val = [NSString stringWithUTF8String:it->second];
myDict[key] = key;
}
CFMutableDictionaryRef myCFDict = (CFMutableDictionaryRef)CFBridgingRetain(myDict);
CFNotificationCenterPostNotification(CFNotificationCenterGetDistributedCenter(), cfIdentifier, NULL, myCFDict, TRUE);
CFRelease(myCFDict);
CFRelease(cfIdentifier);
}
However, there seems to be a memory leak in the NSString *key
object where it should be released automatically. I've tried to implement the conversion on top of objective-C function type and still got the same results... I tend to believe that the mixture between c++ and objective-C, although valid, causes some issues with objective-c garbage collector.
Where did I go wrong in my implementation ?
thanks
map<string, string>
Based on clues which gives accepted answer I suspect what is there actual problem. Your C++ code runs continuously without reaching auto release pool. So when you are using Objective C API where auto release pool is involved this objects are not getting released since auto release pool never gets control.
So I would write this like this:
NSString *ConvertToObjC(const string& s)
{
return [NSString stringWithUTF8String: s.c_str()];
}
NSDictionary *ConvertToObjC(const map<string, string>& cppMap)
// here I use templates which do lots of magic, but this is off topic,
{
NSMutableDictionary *result = [NSMutableDictionary dictionaryWithCapacity: cppMap.count()];
for (const auto& x : cppMap)
{
result[ConvertToObjC(x.first)] = ConvertToObjC(x.second);
}
return result;
}
void IPCNotificationSender::send(const string& identifier,
const map<string, string>& cppMap)
{
@autoreleasepool {
auto ident = ConvertToObjC(identifier);
auto myDic = ConvertToObjC(cppMap);
CFNotificationCenterPostNotification(
CFNotificationCenterGetDistributedCenter(),
(CFStringRef)CFBridgingRetain(ident),
NULL,
(CFDictionaryRef)CFBridgingRetain(myDict),
TRUE);
}
}