Я пытаюсь связаться с оборудованием iOS, чтобы узнать, использует ли устройство встроенные динамики или нет. Все работает нормально, но всякий раз, когда я использую этот код, у меня возникает утечка памяти. Я вызываю его из своего кода C++, помещая его в файл .mm для Objective-C++. Это мой первый раз, когда я пытаюсь использовать Objective-C, поэтому я изо всех сил пытаюсь понять, откуда может исходить утечка. Я даже не знаю, проблема ли это в этом коде, который я немного адаптировал из-за переполнения стека, или что-то в iOS API? Этот код также вызывается очень часто.
Из моих небольших знаний об объективе-c я попытался освободить некоторые объекты внутри функции, но это вызывает проблемы, когда звуковые драйверы меняют настройки (частота дискретизации и т. д.) и вызывает сбои.
bool Headphones::isHeadsetPluggedIn() {
AVAudioSessionRouteDescription* route = [[AVAudioSession sharedInstance] currentRoute];
for (AVAudioSessionPortDescription* desc in [route outputs]) {
if ([[desc portType] isEqualToString:AVAudioSessionPortBuiltInSpeaker])
{
return NO;
}
}
return YES;
}





От
I have tried to release some of the objects within the function
Я делаю вывод, что у вас есть ARC (автоматический подсчет ссылок) инвалид в вашем блоке компиляции Objective-C++. Если у вас нет веской причины, это, вероятно, не лучшая идея, поскольку ARC резко снижает вероятность утечек. Я не думаю, что это источник вашей проблемы, так как я не могу найти какие-либо методы, которые могли бы возвращать сохраненные объекты на первый взгляд.
Значительное количество методов Objective-C, которые вызывает ваш код, имеют возвращаемые типы, помеченные или выведенные как автоматический выпуск. Это решает проблему, заключающуюся в том, что без ARC сохранение возвращаемых объектов означало бы, что вызывающая сторона не могла бы просто использовать выражение вызова метода в другом выражении, но всегда должна была бы присваивать результат переменной, чтобы иметь возможность впоследствии освободить его. в то время как его не сохранение может привести к ситуации использования после освобождения. Например,
AVAudioSessionRouteDescription* route = [[AVAudioSession sharedInstance] currentRoute];
должно быть написано как довольно неудобно
AVAudioSession* session = [AVAudioSession sharedInstance];
AVAudioSessionRouteDescription* route = [session currentRoute];
[session release];
Следовательно, автовыпуск. Это означает, что возвращаемый объект является сохраняется, но помещается в текущий объект автоматического выпуска бассейн. По сути, это стек указателей на объекты, который позже выпускается партиями. Партии разграничены @autoreleasepool блоками. В коде Objective-C обычно вам нужно только явно размещать эти блоки в циклах, которые работают с очень большими или очень многими объектами., чтобы избежать увеличения использования памяти, но цикл выполнения и другие источники событий неявно создают пул, который очищается при возврате обработчика событий.
Поскольку ваш код преимущественно написан на C++, я подозреваю, что вы недостаточно часто используете такой неявный пул, особенно если вы используете традиционный игровой цикл. Решение состоит в том, чтобы обернуть вашу функцию в пул:
bool Headphones::isHeadsetPluggedIn() {
@autoreleasepool
{
AVAudioSessionRouteDescription* route = [[AVAudioSession sharedInstance] currentRoute];
for (AVAudioSessionPortDescription* desc in [route outputs]) {
if ([[desc portType] isEqualToString:AVAudioSessionPortBuiltInSpeaker])
{
return NO;
}
}
return YES;
}
}
Это означает, что любые объекты, помеченные для автоосвобождения во время выполнения этой функции, будут освобождены по возвращении.
Я подозреваю, что это решит вашу проблему.