У меня есть функция C ++, которая получает std::map
объект и преобразовать его в CFMutableDisctionryRef
чтобы использовать его на метод CFNotificationCenterPostNotification
, Вот моя реализация:
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);
}
Тем не менее, кажется, что утечка памяти в NSString *key
объект, где он должен быть освобожден автоматически. Я попытался реализовать преобразование поверх целевого типа функции C и все еще получил те же результаты … Я склонен полагать, что сочетание между c ++ и target-C, хотя и допустимо, вызывает некоторые проблемы с мусором target-c коллектор.
Где я ошибся в своей реализации?
Спасибо
map<string, string>
Основываясь на подсказках, которые дают принятый ответ, я подозреваю, в чем тут проблема.
Ваш код C ++ работает непрерывно без достижения пула автоматического выпуска. Поэтому, когда вы используете Objective C API, где задействован пул автоматического выпуска, эти объекты не освобождаются, поскольку пул автоматического выпуска никогда не получает контроль.
Так что я бы написал это так:
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);
}
}
Я наткнулся на ту же проблему, кажется, проблемное поведение управления памятью в общих проектах C ++ / Objective C.
Решение было создать объекты, которые вы можете вручную освободить их.
В своем коде попробуйте следующее:
for (std::map<const char *, const char *>::iterator it=dict.begin(); it!=dict.end(); ++it)
{
CFStringRef key = CFStringCreateWithCString(NULL, it->first,
kCFStringEncodingMacRoman);
CFStringRef val = CFStringCreateWithCString(NULL, it->second,
kCFStringEncodingMacRoman);
myDict[(__bridge NSString * _Nonnull __strong)(key)] = (__bridge NSString * _Nonnull __strong)(val);
CFRelease(key);
CFRelease(val);
}