Valgrind报告内存泄漏:
[18370]
==18367== Conditional jump or move depends on uninitialised value(s)
==18367== at 0x4C2EDA1: free (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==18367== by 0x40334C: runCmd (main.c:444)
==18367== by 0x40334C: command (main.c:661)
==18367== by 0x40198E: main (main.c:755)
==18367==
==18367==
==18367== HEAP SUMMARY:
==18367== in use at exit: 82,829 bytes in 175 blocks
==18367== total heap usage: 274 allocs, 99 frees, 99,482 bytes allocated
==18367==
==18367== 512 bytes in 1 blocks are definitely lost in loss record 70 of 93
********************* TEST WILDCARDS
***** Press any key to listing all files in current directory...
==18367== at 0x4C2DB8F: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==18367== by 0x402A71: runCmd (main.c:307)
==18367== by 0x402A71: command (main.c:661)
==18367== by 0x40198E: main (main.c:755)
==18367==
==18367== 2,585 (512 direct, 2,073 indirect) bytes in 1 blocks are definitely lost in loss record 80 of 93
==18367== at 0x4C2DB8F: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==18367== by 0x402A5D: runCmd (main.c:305)
==18367== by 0x402A5D: command (main.c:661)
==18367== by 0x40198E: main (main.c:755)
==18367==
==18367== LEAK SUMMARY:
==18367== definitely lost: 1,024 bytes in 2 blocks
==18367== indirectly lost: 2,073 bytes in 6 blocks
==18367== possibly lost: 0 bytes in 0 blocks
==18367== still reachable: 79,732 bytes in 167 blocks
==18367== suppressed: 0 bytes in 0 blocks
==18367== Reachable blocks (those to which a pointer was found) are not shown.
==18367== To see them, rerun with: --leak-check=full --show-leak-kinds=all
==18367==
这是有问题的代码:
main.c:444
(" free(*matrix);
")
int row;
if (*matrix != NULL) {
for (row = 0; row < BUFFER_SIZE; row++) {
free((*matrix)[row]);
}
free(*matrix);
*matrix = NULL;
}
main.c:307
matrix[0] = malloc(BUFFER_SIZE * sizeof(**matrix));
main.c:305
char ***matrix = malloc(BUFFER_SIZE * sizeof(char *));
整个函数runCmd
是
static int runCmd(const char *cmd) {
char *pString1[z];
char *pString[z];
*pString1 = "\0";
*pString = "\0";
bool quote = false;
char **ptr;
struct command shellcommand[64];
char **ptr1;
char **argv;
int argc = 1;
int n = 0;
int status = 0;
char *pString4[z][z];
char **pString5[z];
int i4 = 0;
for (int f = 0; f < z; f++) {
pString5[f] = NULL; /* initialize */
for (i4 = 0; i4 < z; i4++) {
pString4[f][i4] = NULL;
}
}
char ***matrix = malloc(BUFFER_SIZE * sizeof(char *));
// *matrix = malloc(BUFFER_SIZE * sizeof(**matrix));
matrix[0] = malloc(BUFFER_SIZE * sizeof(**matrix));
// if (cmd) {
char *cmdtmp;
char *pString3[64];
cmdtmp = strdup(cmd);
ptr1 = str_split(pString3, cmdtmp, '|');
int w = 0;
int i2 = 0;
for (int i = 0; ptr1[i]; i++) { /* loop for each pipeline */
n++; /* save number of pipelines */
pString5[n] = NULL;
char *string1[z];
int e = 0;
*pString = "\0";
*string1 = strdup(ptr1[i]);
if ((*string1[0] != '\0') &&
!isspace(*string1[0])) {
/* parse_command(w, ptr, string1, pString, pString5, i2, n, quote, i, string, pString1,
e, &argc, &argv, pInt, pString4);
printf("string %s", * string[i]);*/
char *pString2[64];
ptr = str_split(pString2, *string1, ' ');
pString5[i2] = ptr;
i2++;
char *temp = {'\0'};
int y = 0;
int p = 0;
for (int j = 0; ptr[j]; j++) {
if (ptr + j && !quote && strstr(ptr[j], "'")) {
quote = true;
strcpy(temp, ptr[j]);
if (y < 1) {
y++;
}
}
while_quote("e, y, i, ptr, j, temp, *matrix);
bool keep = false;
if (ptr + j) { ;
if (*(ptr + j)[0] == '{') {
keep = true;
}
if (testFn(*(ptr + j))) {
matrix[i][j - p] = concat(*pString1, ptr[j]);
keep = false;
free(*pString1);
continue;
}
char *str;
if (keep) {
str = concat(*pString1, ptr[j]);
*pString1 = concat(str, " ");
free(str);
p++;
} else {
bool b1 = false;
int i3 = j;
pString4[i][0] = *pString;
// printf("i: %d", i);
str = "\0";
b1 = parse(b1, i, &j, &e, ptr, i3, pString, str, pString4[i]);
if (make_args(pString4[i][e - 1], &argc, (const char ***) &argv)) {
write_command(w, argc, argv, matrix);;
w++;
}
else if (!b1) {
for (int r = 0; argv[r] != NULL; r++) {
matrix[i][r] = argv[r];
}
}
}
}
}
bool boo = false;
// dump_argv((const char *) "d", argc, argv, boo);
}
free(*string1);
}
for (int i = 0; i < n; i++) {
shellcommand[i].argv = matrix[i];
}
fflush(NULL);
/* refactor to a function */
pid_t pid;
pid = fork();
if (pid < 0) {
perror("fork failed");
return -1;
}
/* If we are the child process, then go execute the string.*/
if (pid == 0) {
/* spawn(cmd);*/
fork_pipes(n, shellcommand);
}
/*
* We are the parent process.
* Wait for the child to complete.
*/
while (((pid = waitpid(pid, &status, 0)) < 0) && (errno == EINTR));
if (pid < 0) {
fprintf(stderr, "Error from waitpid: %s", strerror(errno));
free(cmdtmp);
if (ptr1) {
for (int i = 0; ptr1[i]; i++) {
free(ptr1[i]);
}
printf("\n");
free(ptr1);
}
return -1;
}
if (WIFSIGNALED(status)) {
fprintf(stderr, "pid %ld: killed by signal %d\n",
(long) pid, WTERMSIG(status));
free(cmdtmp);
if (ptr1) {
for (int i = 0; ptr1[i]; i++) {
free(ptr1[i]);
}
printf("\n");
free(ptr1);
}
return -1;
}
free(cmdtmp);
if (ptr1) {
for (int i = 0; ptr1[i]; i++) {
free(ptr1[i]);
}
printf("\n");
free(ptr1);
}
int row;
if (*matrix != NULL) {
for (row = 0; row < BUFFER_SIZE; row++) {
free((*matrix)[row]);
}
free(*matrix);
*matrix = NULL;
}
int z;
for (int f = 0; f < n; f++) {
for (z = 0; pString4[f][z]; z++) {
free(pString4[f][z]);
}
// free( pString4[f]);
}
//free(* pString4);
//** pString4 = NULL;
size_t idx;
for (int f = 0; n > 1 && f < n; f++) {
for (idx = 0; *(pString5[f] + idx) != NULL; idx++) {
free(*(pString5[f] + idx));
}
free(pString5[f]);
}
// free(** pString5);
*pString5 = NULL;
free(*matrix );
return WEXITSTATUS(status);
}
还有关于相同行的详细报告:
==19171== 512 bytes in 1 blocks are definitely lost in loss record 77 of 101
==19171== at 0x4C2DB8F: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==19171== by 0x402A5D: runCmd (main.c:305)
==19171== by 0x402A5D: command (main.c:661)
==19171== by 0x40194E: main (main.c:760)
==19171==
==19171== 512 bytes in 1 blocks are definitely lost in loss record 78 of 101
==19171== at 0x4C2DB8F: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==19171== by 0x402A71: runCmd (main.c:307)
==19171== by 0x402A71: command (main.c:661)
==19171== by 0x40194E: main (main.c:760)
执行可能没有错误的进程的一些后端代码:
/* Helper function that forks pipes */
void fork_pipes(int n, struct command *cmd) {
int i;
int in = 0;
int fd[2];
for (i = 0; i < n - 1; ++i) {
if (pipe(fd) == -1) {
err_syserr("Failed creating pipe");
}
spawn_proc(in, fd[1], cmd + i);
close(fd[1]);
in = fd[0];
}
if (dup2(in, 0) < 0) {
err_syserr("dup2() failed on stdin for %s: ", cmd[i].argv[0]);
}
/*fprintf(stderr, "%d: executing %s\n", (int) getpid(), cmd[i].argv[0]);*/
fprintf(stderr, "\n");
execvp(cmd[i].argv[0], cmd[i].argv);
err_syserr("failed to execute %s: ", cmd[i].argv[0]);
}
链接到repo
答案 0 :(得分:3)
你有问题的代码的关键是这样的:
char ***matrix = malloc(BUFFER_SIZE * sizeof(char *));
matrix[0] = malloc(BUFFER_SIZE * sizeof(**matrix));
pid = fork();
/* If we are the child process, then go execute the string.*/
if (pid == 0) {
/* spawn(cmd);*/
fork_pipes(n, shellcommand);
}
/*
* We are the parent process.
* Wait for the child to complete.
*/
while (((pid = waitpid(pid, &status, 0)) < 0) && (errno == EINTR));
if (*matrix != NULL) {
for (int row = 0; row < BUFFER_SIZE; row++) {
free((*matrix)[row]);
}
free(*matrix);
*matrix = NULL;
}
free(*matrix );
首先你创建matrix
这是一个指向char**
数组的指针,它基本上看起来像一个3D数组。请注意,sizeof(char*)
与char**
不匹配,因此这是一个错误,但不是一个重要错误。
然后初始化matrix
的第一个元素,现在是char*
的数组。但那些指针是未初始化的。您稍后将*matrix
(又名matrix[0]
)传递给您尚未向我们展示的功能。
所以整个事情都是一团糟,因为类型不匹配,数组很大程度上未被使用,并且大小可能是错误的,我们无法看到{{{}中存在的其他错误1}}。
但泄漏 - 它来自哪里?好吧,你while_quote()
,然后孩子打电话给fork()
。该函数永远不会返回,并且fork_pipes()
在子进程中泄漏,或者它确实返回,然后其余代码错误,因为父逻辑继续在子进程中执行。
你看,当你matrix
时,你最终得到了所有记忆的两份副本,包括fork()
,并且你需要在每个过程中matrix
。
最后,底部的free()
循环似乎调用了未定义的行为,因为它对free()
的元素进行操作,这些元素从未被初始化。最后的matrix
是多余的,另一个是红旗;你永远不会尝试free(*matrix)
,这可能是那里的意思。
编辑:也许你想要这样的东西:
free(matrix)
然后:
/* returns an array of arrays of char*, all of which NULL */
char*** alloc_matrix(unsigned rows, unsigned columns) {
char*** matrix = malloc(rows * sizeof(char**));
if (!matrix) abort();
for (unsigned row = 0; row < rows; row++) {
matrix[row] = malloc(columns * sizeof(char*));
if (!matrix[row]) abort();
for (unsigned column = 0; column < columns; column++) {
matrix[row][column] = NULL;
}
}
return matrix;
}
假设矩阵内的元素(字符串)填充了由/* deallocates an array of arrays of char*, calling free() on each */
void free_matrix(char*** matrix, unsigned rows, unsigned columns) {
for (unsigned row = 0; row < rows; row++) {
for (unsigned column = 0; column < columns; column++) {
free(matrix[row][column]);
}
free(matrix[row]);
}
free(matrix);
}
,malloc()
等创建的字符串,这为您提供了一对匹配的函数,可用于可靠地分配和解除分配你的矩阵。确保在每个分叉进程中释放,而不仅仅是一个。