iOS 外部库中的 Core Foundation 内存泄漏
iOS Core Foundation Memory Leak in External Library
我目前正在尝试使用开源外部库编写应用程序。我有可用的源代码,并且可以在需要时为自己构建一个新副本。
无论如何,在分析我的应用程序时 - 我注意到库中有一些内存泄漏。它很小 - 一次 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 拒绝加载我的框架的新版本,即使我一直在重新编译它。因此,我不得不清除框架的所有引用 - 包括清理构建信息页面 - 并重新添加 "fixed" 版本。
您正在泄露使用 CFURLCreateWithFileSystemPath
创建的返回 CFURLRef
。
您应该将函数从 getURLFromPath
重命名为 createURLFromPath
,以表明返回的 CFURLRef
的所有权正在传递给调用者。然后调用该方法的任何代码负责在完成后释放 CFURLRef
。
我目前正在尝试使用开源外部库编写应用程序。我有可用的源代码,并且可以在需要时为自己构建一个新副本。
无论如何,在分析我的应用程序时 - 我注意到库中有一些内存泄漏。它很小 - 一次 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 拒绝加载我的框架的新版本,即使我一直在重新编译它。因此,我不得不清除框架的所有引用 - 包括清理构建信息页面 - 并重新添加 "fixed" 版本。
您正在泄露使用 CFURLCreateWithFileSystemPath
创建的返回 CFURLRef
。
您应该将函数从 getURLFromPath
重命名为 createURLFromPath
,以表明返回的 CFURLRef
的所有权正在传递给调用者。然后调用该方法的任何代码负责在完成后释放 CFURLRef
。