我有以下代码来循环遍历 /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);
}
但这也没有帮助解决问题。
更新:
感谢我收到的反馈和 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==