C opendir,readdir 错误:free():无效大小,中止(核心转储)

问题描述 投票:0回答:1

我有以下代码来循环遍历 /proc 内的数字目录,并通过进一步进入给定 PID 的目录来获取文件夹的名称:

/proc/PID/cmdline

这是C代码:

  char* getNameByPID(const char* cmdline_CmdLinePath, const int PID){
      char* chrptr_NameOfProcess;
      FILE* fd_CmdLineFile = fopen (cmdline_CmdLinePath, "rt") ;  // open the file for reading text if (fd_CmdLineFile) {
      if (fd_CmdLineFile) {
          chrptr_NameOfProcess = malloc(200);
          if (fscanf(fd_CmdLineFile, "%s", chrptr_NameOfProcess) != 1) {
              free(chrptr_NameOfProcess);
              chrptr_NameOfProcess = NULL;
          }
          fclose(fd_CmdLineFile);
      }   
      return chrptr_NameOfProcess;
  }       
          
  void printInfo(int intHasArgs) {
      DIR* dir_proc = NULL;
      dir_proc = opendir(PROC_DIRECTORY);
          
      if (dir_proc == NULL) {
          perror("Couldn't open the " PROC_DIRECTORY " directory");
      }   
          
      struct dirent* de_DirEntity = NULL;                                                                                                                                                     
      char smaps_CmdLinePath[100];
      char cmdline_CmdLinePath[100];
          
      while ( (de_DirEntity = readdir(dir_proc)) ) {
          if ( de_DirEntity->d_type == DT_DIR ) {
              if ( isNumeric(de_DirEntity->d_name) ) {
                  strcpy(smaps_CmdLinePath, PROC_DIRECTORY);
                  strcpy(cmdline_CmdLinePath, PROC_DIRECTORY);
                  strcat(smaps_CmdLinePath, de_DirEntity->d_name);
                  strcat(cmdline_CmdLinePath, de_DirEntity->d_name);
                  strcat(smaps_CmdLinePath, "/smaps");
                  strcat(cmdline_CmdLinePath, "/cmdline");
                  char* procName = getNameByPID(cmdline_CmdLinePath, atoi(de_DirEntity->d_name));
                  if (procName != NULL && procName[0] != '\0') {
                      printf("%s\n", procName);
                  }
              }
          }
      }   
      closedir(dir_proc) ;
  }

它按预期工作(打印找到的所有数字目录的名称),但最后打印:

free(): invalid size
Aborted (core dumped)

这告诉我存在一些内存泄漏,但如果初始 malloc 不成功,我确实添加了检查并释放内存:

if (fscanf(fd_CmdLineFile, "%s", chrptr_NameOfProcess) != 1) {
                  free(chrptr_NameOfProcess);
                  chrptr_NameOfProcess = NULL;
}

我还尝试添加以下内容:

if (procName != NULL && procName[0] != '\0') {
    printf("%s\n", procName);
    free(procName);
}

但这也没有帮助解决问题。

c
1个回答
0
投票

更新:

感谢我收到的反馈和 Valgrind 的使用,我做了以下更改:

char* getNameByPID(const char* cmdline_CmdLinePath, const int PID){
    char* chrptr_NameOfProcess = NULL;
    FILE* fd_CmdLineFile = fopen (cmdline_CmdLinePath, "rt") ;  // open the file for reading text if (fd_CmdLineFile) {

    if ( fd_CmdLineFile )
    {
        chrptr_NameOfProcess = malloc(200);
        int result = fscanf(fd_CmdLineFile, "%s", chrptr_NameOfProcess);
        fclose( fd_CmdLineFile );

        if ( result != 0 ) {
            return chrptr_NameOfProcess;
        } else {
            free(chrptr_NameOfProcess);
            return NULL;
        }
    }
    fclose( fd_CmdLineFile );

    return NULL;
}

int printInfo(int intHasArgs) {
    DIR* dir_proc = NULL;
    dir_proc = opendir(PROC_DIRECTORY);

    if (dir_proc == NULL) {
        perror("Couldn't open the " PROC_DIRECTORY " directory");
        return 1;
    }

    struct dirent* de_DirEntity = NULL;
    size_t procDirLen = strlen(PROC_DIRECTORY);
    size_t cmdLineLen = strlen("/cmdline");
    size_t smapsLen   = strlen("/smaps");
    char* smaps_CmdLinePath;
    char* cmdline_CmdLinePath;

    while ( (de_DirEntity = readdir(dir_proc)) ) {
        if ( de_DirEntity->d_type == DT_DIR ) {
            if ( isNumeric(de_DirEntity->d_name) ) {
                cmdline_CmdLinePath = malloc(procDirLen + cmdLineLen + strlen(de_DirEntity->d_name));
                smaps_CmdLinePath = malloc(procDirLen + smapsLen + strlen(de_DirEntity->d_name));
                sprintf(cmdline_CmdLinePath, "%s%s/cmdline", PROC_DIRECTORY, de_DirEntity->d_name);
                sprintf(smaps_CmdLinePath, "%s%s/smaps", PROC_DIRECTORY, de_DirEntity->d_name);
                char* procName = getNameByPID(cmdline_CmdLinePath, atoi(de_DirEntity->d_name));
                if (procName != NULL && procName[0] != '\0') {
                    printf("%s\n", procName);
                }
                free(procName);
                free(cmdline_CmdLinePath);
                free(smaps_CmdLinePath);
            }
        }
    }
    closedir(dir_proc) ;
    return 0;
}

printInfo 现在返回一个 int,因此如果 dir_proc 实际上为 NULL,我可以退出(返回 1)。另外,我删除了原来的 cmdline_CmdLinePath[200] 并通过 malloc 动态分配内存,然后释放它。

不幸的是,我已经添加了尽可能多的检查,但:

free(): invalid size
Aborted (core dumped)

问题依然存在。

这是 valgrind 对此的说法(一个片段),尽管我不确定如何解决这个问题:

==20134== Invalid write of size 1
==20134==    at 0x48F098E: __vsprintf_internal (iovsprintf.c:97)
==20134==    by 0x48CF927: sprintf (sprintf.c:30)
==20134==    by 0x109909: printInfo (in /home/alex/Code/c/proc_info/PID)
==20134==    by 0x109DFC: main (in /home/alex/Code/c/proc_info/PID)
==20134==  Address 0x4aa34ff is 0 bytes after a block of size 15 alloc'd
==20134==    at 0x484880F: malloc (vg_replace_malloc.c:446)
==20134==    by 0x1098B0: printInfo (in /home/alex/Code/c/proc_info/PID)
==20134==    by 0x109DFC: main (in /home/alex/Code/c/proc_info/PID)
==20134== 
==20134== Invalid write of size 1
==20134==    at 0x48F098E: __vsprintf_internal (iovsprintf.c:97)
==20134==    by 0x48CF927: sprintf (sprintf.c:30)
==20134==    by 0x109933: printInfo (in /home/alex/Code/c/proc_info/PID)
==20134==    by 0x109DFC: main (in /home/alex/Code/c/proc_info/PID)
==20134==  Address 0x4aa354d is 0 bytes after a block of size 13 alloc'd
==20134==    at 0x484880F: malloc (vg_replace_malloc.c:446)
==20134==    by 0x1098DB: printInfo (in /home/alex/Code/c/proc_info/PID)
==20134==    by 0x109DFC: main (in /home/alex/Code/c/proc_info/PID)
==20134== 
==20134== Syscall param openat(filename) points to unaddressable byte(s)
==20134==    at 0x498353B: open (open64.c:41)
==20134==    by 0x48FB0B5: _IO_file_open (fileops.c:188)
==20134==    by 0x48FB411: _IO_file_fopen@@GLIBC_2.2.5 (fileops.c:280)
==20134==    by 0x48EE6AD: __fopen_internal (iofopen.c:75)
==20134==    by 0x48EE6AD: fopen@@GLIBC_2.2.5 (iofopen.c:86)
==20134==    by 0x109778: getNameByPID (in /home/alex/Code/c/proc_info/PID)
==20134==    by 0x109953: printInfo (in /home/alex/Code/c/proc_info/PID)
==20134==    by 0x109DFC: main (in /home/alex/Code/c/proc_info/PID)
==20134==  Address 0x4aa34ff is 0 bytes after a block of size 15 alloc'd
==20134==    at 0x484880F: malloc (vg_replace_malloc.c:446)
==20134==    by 0x1098B0: printInfo (in /home/alex/Code/c/proc_info/PID)
==20134==    by 0x109DFC: main (in /home/alex/Code/c/proc_info/PID)
==20134== 
/sbin/init
==20134== Conditional jump or move depends on uninitialised value(s)
==20134==    at 0x109968: printInfo (in /home/alex/Code/c/proc_info/PID)
==20134==    by 0x109DFC: main (in /home/alex/Code/c/proc_info/PID)
==20134== 
© www.soinside.com 2019 - 2024. All rights reserved.