如何解决Objective-C代码中的内存泄漏问题?

时间:2019-06-07 08:53:54

标签: c++ objective-c memory-management memory-leaks objective-c++

我正在尝试与iOS硬件进行通信,以查找设备是否正在使用内置扬声器。一切正常,但是每当我使用此代码时,都会发生内存泄漏。我从C ++代码中调用它,方法是将其放入用于Objective-C ++的.mm文件。这是我第一次尝试使用Objective-C,因此我正在努力查看泄漏可能来自何处。我什至不知道这段代码是否有问题,我已经从堆栈溢出或iOS API稍微修改了一下?该代码也经常被调用。

根据我对Objective-C的一点了解,我试图释放函数中的某些对象,但这会在音频驱动程序更改设置(采样率等)并导致崩溃时引起问题。

bool Headphones::isHeadsetPluggedIn() {
    AVAudioSessionRouteDescription* route = [[AVAudioSession sharedInstance] currentRoute];
    for (AVAudioSessionPortDescription* desc in [route outputs]) {
        if ([[desc portType] isEqualToString:AVAudioSessionPortBuiltInSpeaker])
        {
            return NO;
        }
    }
    return YES;
}

1 个答案:

答案 0 :(得分:1)

  1. ARC。

来自

  

我试图释放函数中的某些对象

我推断您在Objective-C ++编译单元中禁用了ARC(自动参考计数)。除非您有充分的理由,否则这可能不是一个好主意,因为ARC可以大大减少泄漏的机会。我认为这不是问题的根源,因为我一眼无法发现可能返回保留对象的任何方法。

  1. 自动发布

您的代码正在调用的许多Objective-C方法都将返回类型标记或推断为自动释放。这可以解决以下问题:没有ARC,保留返回的对象将意味着调用者不能简单地在另一个表达式中使用方法调用表达式,而是始终必须将结果分配给变量才能随后释放它,如果不保留它,可能会导致使用后无法使用的情况。例如,

static void gapSort(int arr[], int len)
{
    int temp, gap, swap;
    gap = len / 2;
    while (1)
    {
        swap = 0;
        for (int i = 0; i < len - gap; i++)
        {
            if (arr[i] > arr[i + gap])
            {
                temp = arr[i];
                arr[i] = arr[i + gap];
                arr[i + gap] = temp;
                swap = 1;
            }
        }
        /* arrDisp(arr, len); */
        if (swap == 0)
        {
            if (gap == 1)
                break;
            gap /= 2;
        }
    }
}

必须写得很尴尬

    AVAudioSessionRouteDescription* route = [[AVAudioSession sharedInstance] currentRoute];

因此,自动释放。这意味着返回的对象 被保留,但被放置在当前的自动发布 pool 中。这实际上是对象指针的堆栈,以后将分批释放。批次由 AVAudioSession* session = [AVAudioSession sharedInstance]; AVAudioSessionRouteDescription* route = [session currentRoute]; [session release]; 块描述。在Objective-C代码中,you usually only need to place these blocks explicitly in loops which operate on very large or very many objects为避免内存使用增加,但runloop和其他事件源隐式创建了一个池,该池在事件处理程序返回时清除。

由于您的代码主要是C ++,我怀疑您没有经常访问这样的隐式池,尤其是在使用传统游戏循环的情况下。解决方案是将函数包装在一个池中:

@autoreleasepool

这意味着在执行此功能期间标记为自动释放的所有对象将在返回时释放。

我怀疑这会解决您的问题。