为什么 C 不从 strtok 设置的 malloc'd char* 中释放内存?
Why isn't C freeing memory from malloc'd char* set by strtok?
此函数从文本文件中读取值,将值分隔为 space 到二维数组中。当我 运行 它时,工作正常 - 但通过 Valgrind 进行的内存泄漏检查证实了 Xcode 的怀疑,即 "char *splitString" 从未被释放,它被调用了两次。我不明白这一点,考虑到我的 "char *buffer" 似乎已经被释放了。非常感谢任何帮助!
int** readMatrixFile(char* inFileName, int** matrix, int sizeY, int sizeX)
{
FILE* matrixFP;
int ii=0, jj=0, fileValid = 1;
char *buffer, *splitString;
const char delim[]=" \n\r";
matrixFP = fopen(inFileName, "r");
if(matrixFP != NULL)
{
/*Check if file is the same size as specified by the command line
*assumed valid until the file is checked*/
splitString = malloc(100*sizeof(char)); <------where allocated
buffer = malloc(5000*sizeof(char));
do
{
fgets(buffer, 5000, matrixFP);
jj=0;
splitString = strtok(buffer, delim);
while(splitString != NULL)
{
jj++;
splitString = strtok(NULL, delim);
}
if(jj!=sizeX)
{
fileValid = 0;
}
ii++;
} while(!feof(matrixFP));
if(ii != sizeY || buffer==NULL)
{
fileValid = 0;
}
free(splitString); <-----Appears to do nothing?
free(buffer);
if(fileValid) /*Files match to specified command line values*/
{
ii=0;
rewind(matrixFP);
matrix = (int**)malloc(sizeY * sizeof(int *));
do
{
matrix[ii] = (int*)malloc(sizeX * sizeof(int));
jj=0;
do
{
fscanf(matrixFP, "%d", &matrix[ii][jj]);
jj++;
} while(jj<sizeX);
ii++;
} while(ii<sizeY && !feof(matrixFP));
}
else
{
printf("Error: File does not match size specified by the command line\n");
}
fclose(matrixFP);
}
else
{
perror("Error: File does not exist or is invalid");
matrix = NULL;
}
return matrix;
}
和 Valgrind 输出:
==14087== Memcheck, a memory error detector
==14087== Copyright (C) 2002-2012, and GNU GPL'd, by Julian Seward et al.
==14087== Using Valgrind-3.8.1 and LibVEX; rerun with -h for copyright info
==14087== Command: ./pmms a b 10 3 10
==14087==
/*irrelevent program output*/
==14087==
==14087== HEAP SUMMARY:
==14087== in use at exit: 200 bytes in 2 blocks
==14087== total heap usage: 21 allocs, 19 frees, 11,680 bytes allocated
==14087==
==14087== 100 bytes in 1 blocks are definitely lost in loss record 1 of 2
==14087== at 0x4A06A2E: malloc (vg_replace_malloc.c:270)
==14087== by 0x400B55: readMatrixFile (matrix_reader.c:35)
==14087== by 0x40095E: main (pmms.c:23)
==14087==
==14087== 100 bytes in 1 blocks are definitely lost in loss record 2 of 2
==14087== at 0x4A06A2E: malloc (vg_replace_malloc.c:270)
==14087== by 0x400B55: readMatrixFile (matrix_reader.c:35)
==14087== by 0x400982: main (pmms.c:24)
==14087==
==14087== LEAK SUMMARY:
==14087== definitely lost: 200 bytes in 2 blocks
==14087== indirectly lost: 0 bytes in 0 blocks
==14087== possibly lost: 0 bytes in 0 blocks
==14087== still reachable: 0 bytes in 0 blocks
==14087== suppressed: 0 bytes in 0 blocks
==14087==
==14087== For counts of detected and suppressed errors, rerun with: -v
==14087== ERROR SUMMARY: 2 errors from 2 contexts (suppressed: 6 from 6)
您在此处更改 splitString
的值:
splitString = strtok(NULL, delim);
这里:
splitString = strtok(buffer, delim);
所以它不再指向要释放的内存块,所以 free()
什么都不做,因为到达这一行时,splitString
将是 NULL
,并且 free(NULL)
被定义为什么也不做。
在 while(splitSring != NULL)
循环中,您正在使用 strtok(3)
对其进行修改。在循环结束时 splitString
将是 NULL
并且实际上您正在调用 free(NULL)
,同时泄漏了最初分配的内存。
首先,你迭代
while(splitString != NULL)
{
...
}
所以在循环完成后 splitString
是 NULL
,而 free(NULL)
什么都不做。
其次,一旦你分配了一个一百字节的内存块
splitString = malloc(100*sizeof(char)); // (*)
对 splitString
变量的下一个引用是赋值:
splitString = strtok(buffer, delim);
所以,无论存储在变量中的是什么,它都被覆盖了! splitString
现在指向 buffer
块中的某处,分配在 (*)
的块地址将永远丢失。顺便说一句,这表明您从不使用该块,并且实际上不需要分配它。
这不是对您问题的直接回答,只是一个可能有助于完全避免问题的建议:
当使用 strtok()
和 family 时,您不需要为您用来捕获 return 值的对象显式分配内存:
char delim[] = {" \n\t"}; //or whatever delimitors you need
char *tok = NULL;
tok = strtok(stringToParse, delim);
while(tok)
{
//do something with tok
...
//get next token:
tok = strtok(NULL, delim);
}
并且,如图所示使用时无需释放 tok
。
此函数从文本文件中读取值,将值分隔为 space 到二维数组中。当我 运行 它时,工作正常 - 但通过 Valgrind 进行的内存泄漏检查证实了 Xcode 的怀疑,即 "char *splitString" 从未被释放,它被调用了两次。我不明白这一点,考虑到我的 "char *buffer" 似乎已经被释放了。非常感谢任何帮助!
int** readMatrixFile(char* inFileName, int** matrix, int sizeY, int sizeX)
{
FILE* matrixFP;
int ii=0, jj=0, fileValid = 1;
char *buffer, *splitString;
const char delim[]=" \n\r";
matrixFP = fopen(inFileName, "r");
if(matrixFP != NULL)
{
/*Check if file is the same size as specified by the command line
*assumed valid until the file is checked*/
splitString = malloc(100*sizeof(char)); <------where allocated
buffer = malloc(5000*sizeof(char));
do
{
fgets(buffer, 5000, matrixFP);
jj=0;
splitString = strtok(buffer, delim);
while(splitString != NULL)
{
jj++;
splitString = strtok(NULL, delim);
}
if(jj!=sizeX)
{
fileValid = 0;
}
ii++;
} while(!feof(matrixFP));
if(ii != sizeY || buffer==NULL)
{
fileValid = 0;
}
free(splitString); <-----Appears to do nothing?
free(buffer);
if(fileValid) /*Files match to specified command line values*/
{
ii=0;
rewind(matrixFP);
matrix = (int**)malloc(sizeY * sizeof(int *));
do
{
matrix[ii] = (int*)malloc(sizeX * sizeof(int));
jj=0;
do
{
fscanf(matrixFP, "%d", &matrix[ii][jj]);
jj++;
} while(jj<sizeX);
ii++;
} while(ii<sizeY && !feof(matrixFP));
}
else
{
printf("Error: File does not match size specified by the command line\n");
}
fclose(matrixFP);
}
else
{
perror("Error: File does not exist or is invalid");
matrix = NULL;
}
return matrix;
}
和 Valgrind 输出:
==14087== Memcheck, a memory error detector
==14087== Copyright (C) 2002-2012, and GNU GPL'd, by Julian Seward et al.
==14087== Using Valgrind-3.8.1 and LibVEX; rerun with -h for copyright info
==14087== Command: ./pmms a b 10 3 10
==14087==
/*irrelevent program output*/
==14087==
==14087== HEAP SUMMARY:
==14087== in use at exit: 200 bytes in 2 blocks
==14087== total heap usage: 21 allocs, 19 frees, 11,680 bytes allocated
==14087==
==14087== 100 bytes in 1 blocks are definitely lost in loss record 1 of 2
==14087== at 0x4A06A2E: malloc (vg_replace_malloc.c:270)
==14087== by 0x400B55: readMatrixFile (matrix_reader.c:35)
==14087== by 0x40095E: main (pmms.c:23)
==14087==
==14087== 100 bytes in 1 blocks are definitely lost in loss record 2 of 2
==14087== at 0x4A06A2E: malloc (vg_replace_malloc.c:270)
==14087== by 0x400B55: readMatrixFile (matrix_reader.c:35)
==14087== by 0x400982: main (pmms.c:24)
==14087==
==14087== LEAK SUMMARY:
==14087== definitely lost: 200 bytes in 2 blocks
==14087== indirectly lost: 0 bytes in 0 blocks
==14087== possibly lost: 0 bytes in 0 blocks
==14087== still reachable: 0 bytes in 0 blocks
==14087== suppressed: 0 bytes in 0 blocks
==14087==
==14087== For counts of detected and suppressed errors, rerun with: -v
==14087== ERROR SUMMARY: 2 errors from 2 contexts (suppressed: 6 from 6)
您在此处更改 splitString
的值:
splitString = strtok(NULL, delim);
这里:
splitString = strtok(buffer, delim);
所以它不再指向要释放的内存块,所以 free()
什么都不做,因为到达这一行时,splitString
将是 NULL
,并且 free(NULL)
被定义为什么也不做。
在 while(splitSring != NULL)
循环中,您正在使用 strtok(3)
对其进行修改。在循环结束时 splitString
将是 NULL
并且实际上您正在调用 free(NULL)
,同时泄漏了最初分配的内存。
首先,你迭代
while(splitString != NULL)
{
...
}
所以在循环完成后 splitString
是 NULL
,而 free(NULL)
什么都不做。
其次,一旦你分配了一个一百字节的内存块
splitString = malloc(100*sizeof(char)); // (*)
对 splitString
变量的下一个引用是赋值:
splitString = strtok(buffer, delim);
所以,无论存储在变量中的是什么,它都被覆盖了! splitString
现在指向 buffer
块中的某处,分配在 (*)
的块地址将永远丢失。顺便说一句,这表明您从不使用该块,并且实际上不需要分配它。
这不是对您问题的直接回答,只是一个可能有助于完全避免问题的建议:
当使用 strtok()
和 family 时,您不需要为您用来捕获 return 值的对象显式分配内存:
char delim[] = {" \n\t"}; //or whatever delimitors you need
char *tok = NULL;
tok = strtok(stringToParse, delim);
while(tok)
{
//do something with tok
...
//get next token:
tok = strtok(NULL, delim);
}
并且,如图所示使用时无需释放 tok
。