在OSX上,Valgrind报告了内存泄漏,它来自哪里

On OSX Valgrind reports this memory leak, Where is it coming from?

本文关键字:泄漏 OSX Valgrind 报告 内存      更新时间:2023-10-16

在OSX上,Valgrind报告了此内存泄漏,它来自哪里?该代码是用g++作为c++代码进行c编译的(我这样做是为了函数重载)。

==13088==在264的丢失记录82中,1个块中的18个字节肯定丢失==13088==在0x1F25DC:malloc_zone_malloc(vg_replace_malloc.c:267)===13088===通过0xA1AEDA:malloc_set_zone_name(在/usr/lib/system/libsystem_c.dylib中)===13088===通过0xA1B4A7:_malloc_initialize(在/usr/lib/system/libsystem_c.dylib中)===13088===通过0xA1B5DD:malloc_good_size(在/usr/lib/system/libsystem_c.dylib中)===13088===由0x4EFA6E:__CFStringChangeSizeMultiple(在/System/Library/Frameworks/CoreFoundation.framework/Versions/A/CoreFoundation中)==13088==by 0x4F3900:CFStringAppend(在/System/Library/Frameworks/CoreFoundation.framework/Versions/A/CoreFoundation中)==13088==by 0x506F91:_convertToURLRepresentation(在/System/Library/Frameworks/CoreFoundation.framework/Versions/A/CoreFoundation中)==13088==by 0x60F963:_CFURLInit(在/System/Library/Frameworks/CoreFoundation.framework/Versions/A/CoreFoundation中)===13088===通过0x4FF268:CFURLCreateWithFileSystemPathRelativeToBase(在/System/Library/Frameworks/CoreFoundation.framework/Versions/A/CoreFoundation中)===13088===通过0x4FF8EE:CFURLCreateWithFileSystemPath(在/System/Library/Frameworks/CoreFoundation.framework/Versions/A/CoreFoundation中)===13088===通过0x515735:_CFBundleGetMainBundleAlreadyLocked(在/System/Library/Frameworks/CoreFoundation.framework/Versions/A/CoreFoundation中)===13088===通过0x515663:CFBundleGetMainBundle(在/System/Library/Frameworks/CoreFoundation.framework/Versions/A/CoreFoundation中)==13088==by 0x539533:cacheBundleInfo(在/System/Library/Frameworks/CoreFoundation.framework/Versions/A/CoreFoundation中)===13088===通过0x5394B3:_CFAppVersionCheckLessThan(在/System/Library/Frameworks/CoreFoundation.framework/Versions/A/CoreFoundation中)===13088===通过0x56C35B:__CFInitialize(在/System/Library/Frameworks/CoreFoundation.framework/Versions/A/CoreFoundation中)===13088===由0x8FE11243:ImageLoaderMachO::doImageInit(ImageLoader::LinkContext const&)(在/usr/lib/dyd中)===13088===通过0x8FE10CB3:ImageLoaderMachO::doInitialization(ImageLoader::LinkContext const&)(在/usr/lib/dyd中)===13088===由0x8FE0E21F:ImageLoader::recursiveInitialization===13088===由0x8FE0E1B5:ImageLoader::recursiveInitialization===13088===由0x8FE0F1BF:ImageLoader::runInitializers===13088===通过0x8FE03655:dyld::initializeMainExecutable()(在/usr/lib/dyd中)==13088==by 0x8FE07EF1:dyld::_main(macho_header const*,unsigned long,int,char const**,char const***,char const**)(在/usr/lib/dyd中)==13088==by 0x8FE012EE:dyldbootstrap::start(macho_header const*,int,char const**,long,macho_head const*)(在/usr/lib/dyd中)===13088===通过0x8FE01062:_dyld_start(在/usr/lib/dyd中)==13088==通过0xFFF:???

编辑:还有,我该如何释放这些记忆?

分配完全超出您的控制范围;免费对你来说同样是不可能的。应将其添加到已知、检测到、记录但被忽略的项目列表中(术语为"抑制")。

当我在MacOS X 10.7.2上运行valgrind 3.7.0下的程序时,我会得到一个总结,比如:

==71989== 
==71989== HEAP SUMMARY:
==71989==     in use at exit: 6,191 bytes in 33 blocks
==71989==   total heap usage: 33 allocs, 0 frees, 6,191 bytes allocated
==71989== 
==71989== LEAK SUMMARY:
==71989==    definitely lost: 0 bytes in 0 blocks
==71989==    indirectly lost: 0 bytes in 0 blocks
==71989==      possibly lost: 0 bytes in 0 blocks
==71989==    still reachable: 6,191 bytes in 33 blocks
==71989==         suppressed: 0 bytes in 0 blocks
==71989== Rerun with --leak-check=full to see details of leaked memory
==71989== 
==71989== For counts of detected and suppressed errors, rerun with: -v
==71989== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 1 from 1)

这来自一个不进行显式内存分配的程序——printf()可能会触发一些分配,但这些字节中的大多数都是在系统库中分配的。很明显,您为回溯(--num-callers=N)设置了一个比正常值更深的值。

请参阅手册了解如何正确添加抑制记录,但valgrind --help提供了:

--num-callers=<number>    show <number> callers in stack traces [12]
--error-limit=no|yes      stop showing new errors if too many? [yes]
--error-exitcode=<number> exit code to return if errors found [0=disable]
--show-below-main=no|yes  continue stack traces below main() [no]
--suppressions=<filename> suppress errors described in <filename>
--gen-suppressions=no|yes|all    print suppressions for errors? [no]

因此,您可以让valgrind生成抑制字符串,以便添加到文件中,然后在后续运行中使用。

Extra options read from ~/.valgrindrc, $VALGRIND_OPTS, ./.valgrindrc

它看起来更像是在您正在使用的某个库中,如果是这样,请确保您正确使用了库的API,但也要知道,有时库会分配全局资源,例如,在初始化时,直到程序退出时才会释放这些资源。

例如,考虑这种情况:

void init_lib(){
    static char *buf=NULL;
    if (buf==NULL) {
       buf = malloc(18);
    }
    .....
}

库如何在退出前释放此缓冲区?它不能,直到程序退出并且操作系统回收了它的内存。

请参阅此处的常见陷阱

编辑:从技术上讲,在上面的例子中,正如下面的一条评论所建议的那样,buf可以是免费的,但许多库并不介意这样做,因为buf将在程序期间使用,并且当程序退出时,内存将被回收,所以valgrind将其报告为内存泄漏。

在OS X上,您需要使用--dsymutil=yes运行valgrind以获得有关泄漏位置的更多有用信息

我不确定您运行的是哪个版本的osx。但在我运行的版本中,valgrind报告这些错误是可以忽略的。