Как исправить проблему с утечкой памяти в коде Objective-C?

Я пытаюсь связаться с оборудованием 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;
}
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
1
0
807
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий
  1. АРК.

От

I have tried to release some of the objects within the function

Я делаю вывод, что у вас есть ARC (автоматический подсчет ссылок) инвалид в вашем блоке компиляции Objective-C++. Если у вас нет веской причины, это, вероятно, не лучшая идея, поскольку ARC резко снижает вероятность утечек. Я не думаю, что это источник вашей проблемы, так как я не могу найти какие-либо методы, которые могли бы возвращать сохраненные объекты на первый взгляд.

  1. Авторелиз

Значительное количество методов 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;
    }
}

Это означает, что любые объекты, помеченные для автоосвобождения во время выполнения этой функции, будут освобождены по возвращении.

Я подозреваю, что это решит вашу проблему.

Другие вопросы по теме