【问题标题】:iOS Core Foundation Memory Leak in External Library外部库中的 iOS Core Foundation 内存泄漏
【发布时间】:2015-12-09 03:42:20
【问题描述】:

我目前正在尝试使用开源的外部库编写应用程序。我有可用的源代码,并且可以在需要时为自己构建一个新副本。

无论如何,在分析我的应用程序时 - 我注意到库中有一些内存泄漏。它很小 - 128b 一次 - 但我还是希望 一开始就有内存泄漏。

这是代码。我写的修改代码在上面(泄漏),原始代码在底部(泄漏)。

CFURLRef getURLFromPath(const char * path) {
  //modified code to hopefully clean up after myself
  CFStringRef cfTotalPath = CFStringCreateWithCString (NULL, path, kCFStringEncodingUTF8);
  CFURLRef cURL = CFURLCreateWithFileSystemPath(NULL, cfTotalPath, kCFURLPOSIXPathStyle, false);
  CFRelease(cfTotalPath);

  return cURL;

  //original code
  /*CFStringRef cfTotalPath = CFStringCreateWithCString (kCFAllocatorDefault,
      path, kCFStringEncodingUTF8);

  return CFURLCreateWithFileSystemPath(kCFAllocatorDefault, cfTotalPath,
      kCFURLPOSIXPathStyle, false);*/

}

我对 iOS 编程比较陌生;我正在实际设备上调试,我知道有时 Instruments 在泄漏时会给出误报。

这真令人生气,因为这一段代码是我的泄漏堆栈跟踪中的最后一步......老实说,我不知道如何修复它。

编辑:根据我的阅读,Apple 不介意偶尔出现内存泄漏。我将继续编程,因为这个过程在我的应用程序中每个音乐文件只发生一次 - 分析 BPM 的曲目(分析后保存)。

Edit2:这是引用代码。我已经添加了所有的 CFRelease(fileURL),但它仍然泄漏:

uint_t aubio_sink_apple_audio_open(aubio_sink_apple_audio_t *s) {

  if (s->samplerate == 0 || s->channels == 0) return AUBIO_FAIL;

  AudioStreamBasicDescription clientFormat;
  memset(&clientFormat, 0, sizeof(AudioStreamBasicDescription));
  clientFormat.mFormatID         = kAudioFormatLinearPCM;
  clientFormat.mSampleRate       = (Float64)(s->samplerate);
  clientFormat.mFormatFlags      = kAudioFormatFlagIsSignedInteger | kAudioFormatFlagIsPacked;
  clientFormat.mChannelsPerFrame = s->channels;
  clientFormat.mBitsPerChannel   = sizeof(short) * 8;
  clientFormat.mFramesPerPacket  = 1;
  clientFormat.mBytesPerFrame    = clientFormat.mBitsPerChannel * clientFormat.mChannelsPerFrame / 8;
  clientFormat.mBytesPerPacket   = clientFormat.mFramesPerPacket * clientFormat.mBytesPerFrame;
  clientFormat.mReserved         = 0;

  AudioFileTypeID fileType = kAudioFileWAVEType;
  CFURLRef fileURL = getURLFromPath(s->path);
  bool overwrite = true;
  OSStatus err = noErr;
  err = ExtAudioFileCreateWithURL(fileURL, fileType, &clientFormat, NULL,
     overwrite ? kAudioFileFlags_EraseFile : 0, &s->audioFile);
  if (err) {
    char_t errorstr[20];
    AUBIO_ERR("sink_apple_audio: error when trying to create %s with "
        "ExtAudioFileCreateWithURL (%s)\n", s->path,
        getPrintableOSStatusError(errorstr, err));
    goto beach;
  }
  if (createAubioBufferList(&s->bufferList, s->channels, s->max_frames * s->channels)) {
    AUBIO_ERR("sink_apple_audio: error when creating buffer list for %s, "
        "out of memory? \n", s->path);
    goto beach;
  }

  //added release code
  CFRelease(fileURL);
  return AUBIO_OK;

beach:
  //added release code
  CFRelease(fileURL);
  return AUBIO_FAIL;
}

EDIT3:这是截图

EDIT4:原来的解决方案确实有效,XCode 拒绝加载我的框架的新版本,即使我一直在重新编译它。所以,我不得不清除框架的所有引用——包括清理构建信息页面——并重新添加“固定”版本。

【问题讨论】:

  • 在您的代码上运行分析器。它是否报告您的代码有任何问题?如果是这样,请解决问题,然后查看是否仍有泄漏。
  • 嘿 rmaddy,我刚刚对我的项目进行了分析。出现的唯一错误围绕单元原型 ID 和启动屏幕(由于我的故事板不完整)。我的项目仍然很不完整而且很小,我认为我应该在继续下一个大块之前执行“代码清理”和审查。这就是我发现这个非常小的内存泄漏的原因
  • 你是在模拟器还是真机上测试?仅在真实设备上进行泄漏测试。
  • 真机,iPhone 5S 8.3。还添加了堆栈跟踪的屏幕截图。错误是否与 Apple 提供的方法“ExtAudioFileCreateWithURL”有关?...嗯

标签: ios objective-c memory-leaks core-foundation


【解决方案1】:

您正在泄漏使用CFURLCreateWithFileSystemPath 创建的返回的CFURLRef

您应该将函数从getURLFromPath 重命名为createURLFromPath,以表明返回的CFURLRef 的所有权正在传递给调用者。然后任何调用该方法的代码都负责在完成后释放CFURLRef

【讨论】:

  • 感谢您的帮助;我在调用它的代码中添加了 CFRelease(fileURL) ,但仍然遇到链接。我已将调用代码添加到我原来的问题中。
  • 嘿 rmaddy!您的解决方案确实奏效了;尽管我进行了构建和清理,XCode 一直在缓存旧版本的框架。我最终不得不删除对库的所有引用(包括从框架搜索路径中删除文件夹引用),并读取一个新的。然而,简洁的是,框架也从 .41 升级到了 .42,所以我也得到了免费的错误修复升级!
猜你喜欢
  • 1970-01-01
  • 2011-07-16
  • 1970-01-01
  • 1970-01-01
  • 2015-02-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-02-18
相关资源
最近更新 更多