【发布时间】:2016-05-05 03:57:20
【问题描述】:
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]);
}
使用所有代码 https://github.com/montao/openshell 链接到 repo
【问题讨论】:
-
valgrind 输出清楚地表明泄漏的对象分配在
runCmd,而不是write_command。所以,你应该先看看runCmd。 -
为什么要将
malloc()的结果保存到三指针?这里有太多代码需要筛选。你有没有通过调试器? -
标题“3 start 程序员有内存问题”为什么我不惊讶..
-
fork_pipes()是做什么的?它会返回吗? -
这是一个非常可怕的功能。我说这不是为了让你难堪,而是要指出这样一个冗长而杂乱无章的函数会让你很难理解和调试,让其他人也能做到这一点。如果您尝试使用标准技术(例如将代码分解为更小的函数)来简化代码,这将对您有所帮助。
标签: c memory-leaks valgrind