【问题标题】:Valgrind check for memory leak in CValgrind 检查 C 中的内存泄漏
【发布时间】:2016-08-08 11:01:58
【问题描述】:

我们用 C 语言编写了一套代码,它将目录中的 Matlab 数据文件 (.mat) 作为输入,它还调用 GSL 函数来搜索多项式的根并生成随机数。我们正在开发 OSX。我们使用Valgrind 来检查是否有任何内存泄漏,因为我们在代码中使用了很多mallocfree。它确实对我们在许多地方发现内存泄漏有很大帮助。但是,仍然有一个我们无法修复。问题存在于名为maxphaseutils.c的子程序中的函数listfileswext(它列出了具有给定扩展名的目录中的所有文件,即.mat):

char ** listfileswext (const char *ext, const char *dirName, size_t *nFiles, size_t *maxFileNameLen)
{
    /*printf("------- %s -------\n",ext);
    printf("Extension string length %zu\n",strlen(ext));*/
  char *pattern = (char *)malloc((3+strlen(ext))*sizeof(char));
  DIR *dp;
  struct dirent *ep;
  char **fileList;
  size_t lpc;

  pattern[0] = '*';
  pattern[1] = '.';
  pattern[2] = '\0';
  strcat(pattern,ext);

  /*printf("Pattern %s\n",pattern);*/
  /* Step 1: Count the number of files with the required 
     extension.
  */
  size_t countValidFiles = 0;
  dp = opendir(dirName);
  if (dp != NULL){
      while ((ep = readdir(dp))){
            /*printf("Checking file %s\n",ep->d_name);*/
            if(!fnmatch(pattern, ep->d_name, (FNM_FILE_NAME|FNM_PERIOD))){
                /* Match. Increment counter */
                /*printf("found match with pattern %s\n",pattern);*/
                countValidFiles++;
            }
      }
      (void) closedir (dp);
      /*
        Apparently, there is no need to free ep as it is declared to be 'static' in the readdir function
      */
  }
  else{
    printf ("Couldn't open the directory %s\n",dirName);
    free(pattern);
    return NULL;
  }
  *nFiles = countValidFiles;
  /* Step 2: Create storage for list of filenames */
  fileList = (char **)malloc(countValidFiles*sizeof(char *));
  /* Can't find a better way than to repeat the whole loop again */
  countValidFiles = 0;
  dp = opendir(dirName);
  if (dp != NULL){
      while ((ep = readdir(dp))){
            if(!fnmatch(pattern, ep->d_name, (FNM_FILE_NAME|FNM_PERIOD))){
                fileList[countValidFiles] = (char *)malloc(strlen(ep->d_name)*sizeof(char));
                strcpy(fileList[countValidFiles],ep->d_name);
                /* Match. Increment counter */
                countValidFiles++;
            }
      }
      (void) closedir (dp);
  }
  else{
    printf ("Couldn't open the directory %s\n",dirName);
    return NULL;
  }

    /*Find longest filename */
    size_t fileNameLen;
    *maxFileNameLen = 0;
    size_t lpc1;
    for (lpc1 = 0; lpc1 < *nFiles; lpc1++){
        fileNameLen = strlen(fileList[lpc1]);
        if ( fileNameLen > *maxFileNameLen)
            *maxFileNameLen = fileNameLen;
    }

  /* Wrap up */
  free(pattern);
  return fileList;
}   

在这个函数中,变量fileList被调用

char **inputFileList;
    size_t nInputFiles, maxFileNameLen;
    inputFileList = listfileswext("mat", simDataDir, &nInputFiles, &maxFileNameLen);

然后释放

for(lpc1 = 0; lpc1 < nInputFiles; lpc1++){
        /* Free up dynamically allocated memory for file list*/
        free(inputFileList[lpc1]);
    }
    /* Free up dynamically allocated memory */
free(inputFileList);

在main函数中如上图。如您所见,fileList 在 main 中被释放为 inputFileList,而不是在分配的函数 (listfileswext) 中。我们认为没关系。运行Valgrind后,显示

==8643== Invalid write of size 8
==8643==    at 0x101921031: _platform_memmove$VARIANT$Unknown (in /usr/lib/system/libsystem_platform.dylib)
==8643==    by 0x1016E33AD: stpcpy (in /usr/lib/system/libsystem_c.dylib)
==8643==    by 0x101755F96: __strcpy_chk (in /usr/lib/system/libsystem_c.dylib)
==8643==    by 0x1000044B2: listfileswext (maxphaseutils.c:153)
==8643==    by 0x100005FBD: main (perfeval_snglproc.c:41)
==8643==  Address 0x104c6381d is 13 bytes inside a block of size 20 alloc'd
==8643==    at 0x100010EBB: malloc (vg_replace_malloc.c:303)
==8643==    by 0x10000447C: listfileswext (maxphaseutils.c:152)
==8643==    by 0x100005FBD: main (c:41)

==8643== Invalid read of size 8
==8643==    at 0x101921040: _platform_memmove$VARIANT$Unknown (in /usr/lib/system/libsystem_platform.dylib)
==8643==    by 0x101756127: __strcat_chk (in /usr/lib/system/libsystem_c.dylib)
==8643==    by 0x1000060CE: main (perfeval_snglproc.c:67)
==8643==  Address 0x104c63224 is 4 bytes inside a block of size 11 alloc'd
==8643==    at 0x100010EBB: malloc (vg_replace_malloc.c:303)
==8643==    by 0x10000447C: listfileswext (maxphaseutils.c:152)
==8643==    by 0x100005FBD: main (perfeval_snglproc.c:41)

这里perfeval_snglproc.c 是主要的。此外,还有以下一堆似乎与我们制作的功能无关的人员(我们可能无法控制这些系统文件):

==8643== 168 bytes in 7 blocks are possibly lost in loss record 657 of 1,081
==8643==    at 0x10001178B: malloc_zone_calloc (vg_replace_malloc.c:717)
==8643==    by 0x1019C737C: NXHashInsert (in /usr/lib/libobjc.A.dylib)
==8643==    by 0x1019C746F: _NXHashRehashToCapacity (in /usr/lib/libobjc.A.dylib)
==8643==    by 0x1019C73B9: NXHashInsert (in /usr/lib/libobjc.A.dylib)
==8643==    by 0x1019D6687: realizeClass(objc_class*) (in /usr/lib/libobjc.A.dylib)
==8643==    by 0x1019D5B53: realizeClass(objc_class*) (in /usr/lib/libobjc.A.dylib)
==8643==    by 0x1019CA38D: look_up_class (in /usr/lib/libobjc.A.dylib)
==8643==    by 0x1019CA1B9: objc_getFutureClass (in /usr/lib/libobjc.A.dylib)
==8643==    by 0x101D51D3F: __CFInitialize (in /System/Library/Frameworks/CoreFoundation.framework/Versions/A/CoreFoundation)
==8643==    by 0x7FFF5FC12BC7: ImageLoaderMachO::doImageInit(ImageLoader::LinkContext const&) (in /usr/lib/dyld)
==8643==    by 0x7FFF5FC12E8C: ImageLoaderMachO::doInitialization(ImageLoader::LinkContext const&) (in /usr/lib/dyld)
==8643==    by 0x7FFF5FC0F890: ImageLoader::recursiveInitialization(ImageLoader::LinkContext const&, unsigned int, ImageLoader::InitializerTimingList&, ImageLoader::UninitedUpwards&) (in /usr/lib/dyld)
==8643== 
==8643== 168 (32 direct, 136 indirect) bytes in 1 blocks are definitely lost in loss record 658 of 1,081
==8643==    at 0x10001117C: malloc_zone_malloc (vg_replace_malloc.c:305)
==8643==    by 0x101D6FF79: CFUniCharGetUnicodePropertyDataForPlane (in /System/Library/Frameworks/CoreFoundation.framework/Versions/A/CoreFoundation)
==8643==    by 0x101D6FEBE: CFUniCharGetNumberOfPlanesForUnicodePropertyData (in /System/Library/Frameworks/CoreFoundation.framework/Versions/A/CoreFoundation)
==8643==    by 0x101D6F9A3: __CFUniCharLoadDecompositionTable (in /System/Library/Frameworks/CoreFoundation.framework/Versions/A/CoreFoundation)
==8643==    by 0x101D6F048: CFUniCharDecompose (in /System/Library/Frameworks/CoreFoundation.framework/Versions/A/CoreFoundation)
==8643==    by 0x101D681CE: CFStringGetFileSystemRepresentation (in /System/Library/Frameworks/CoreFoundation.framework/Versions/A/CoreFoundation)
==8643==    by 0x101E91929: _CFURLCreateWithFileSystemPath (in /System/Library/Frameworks/CoreFoundation.framework/Versions/A/CoreFoundation)
==8643==    by 0x101D693D9: _CFBundleCopyBundleURLForExecutableURL (in /System/Library/Frameworks/CoreFoundation.framework/Versions/A/CoreFoundation)
==8643==    by 0x101D63DE4: _CFBundleGetMainBundleAlreadyLocked (in /System/Library/Frameworks/CoreFoundation.framework/Versions/A/CoreFoundation)
==8643==    by 0x101D63D5A: CFBundleGetMainBundle (in /System/Library/Frameworks/CoreFoundation.framework/Versions/A/CoreFoundation)
==8643==    by 0x101D8C0A7: _CFPrefsGetCacheStringForBundleID (in /System/Library/Frameworks/CoreFoundation.framework/Versions/A/CoreFoundation)
==8643==    by 0x101EDADC8: __50+[CFPrefsSearchListSource withSnapshotSearchList:]_block_invoke (in /System/Library/Frameworks/CoreFoundation.framework/Versions/A/CoreFoundation)

请帮忙!提前致谢!

【问题讨论】:

    标签: c matlab memory-leaks valgrind


    【解决方案1】:

    根据this,泄漏不是由您的程序引起的,而是由系统库引起的。

    对于错误,为c-string分配空间时,您需要为尾随零腾出空间,因此更改

     fileList[countValidFiles] = (char *)malloc(strlen(ep->d_name)*sizeof(char));
    

     fileList[countValidFiles] = (char *)malloc((strlen(ep->d_name) + 1)*sizeof(char));
    

    【讨论】:

    • sizeof(char)根据定义始终为 1,因此您可以省略这些(请参阅C99 §6.5.3.4 number 3当应用于具有 char 类型的操作数时,无符号字符,或有符号字符,(或其合格版本)结果为 1。)
    • 有些平台char大小不一样,看this question
    • 是的,但是对于CHAR_BIT > 8 的平台,sizeof(char) 也会返回 1。这是因为这里的大小以 bytes 为单位,CHAR_BIT 定义了 一个字节的大小。另见this questionthis questionC FAQ entry。因此,在具有CHAR_BIT == 16 的机器上,malloc(1) 至少会分配 16 位,malloc(2) 至少会分配 32 位……
    猜你喜欢
    • 1970-01-01
    • 2013-01-26
    • 2020-03-31
    • 2016-03-15
    • 1970-01-01
    • 1970-01-01
    • 2021-11-28
    • 2015-02-28
    • 2015-06-28
    相关资源
    最近更新 更多