我在C中使用getline从stdin读取时遇到内存泄漏,尽管确保释放了所有的mallocs,但在构建一个简单的shell时问题仍然存在。作为一个C新手,我正在寻找在使用getline进行文件输入时如何正确处理内存的建议。
这是我用来读这行的代码
char *readline(int *eof)
{
char *input = NULL;
size_t bufsize = 0;
*eof = getline(&input, &bufsize, stdin);
return (input);
}
这是实际的主要功能。
while (status)
{
mode = isatty(STDIN_FILENO);
if (mode != 0)
{
write(STDOUT_FILENO, "$ ", 3);
}
line = readline(&eof);
if (eof == -1)
{
exit(EXIT_FAILURE);
}
args = tokenize(line);
status = hsh_execute(args, env, argv[0]);
i = 0;
while(args[i] != NULL)
{
free(args[i]);
i++;
}
free(args);
free(line);
}
这是当我运行命令echo“/bin/ls”时valgrind返回的错误|./ shell
==33899== Invalid free() / delete / delete[] / realloc()
==33899== at 0x484B27F: free (in /usr/libexec/valgrind/vgpreload_memcheck-amd64-linux.so)
==33899== by 0x10980D: main (shell.c:40)
==33899== Address 0x4a96040 is 0 bytes inside a block of size 120 free'd
==33899== at 0x484B27F: free (in /usr/libexec/valgrind/vgpreload_memcheck-amd64-linux.so)
==33899== by 0x1097D5: main (shell.c:36)
==33899== Block was alloc'd at
==33899== at 0x4848899: malloc (in /usr/libexec/valgrind/vgpreload_memcheck-amd64-linux.so)
==33899== by 0x48EB1A2: getdelim (iogetdelim.c:62)
==33899== by 0x1096CA: readline (readline.c:12)
==33899== by 0x10976B: main (shell.c:26)
==33899==
==33899==
==33899== HEAP SUMMARY:
==33899== in use at exit: 120 bytes in 1 blocks
==33899== total heap usage: 4 allocs, 4 frees, 4,848 bytes allocated
==33899==
==33899== LEAK SUMMARY:
==33899== definitely lost: 0 bytes in 0 blocks
==33899== indirectly lost: 0 bytes in 0 blocks
==33899== possibly lost: 0 bytes in 0 blocks
==33899== still reachable: 120 bytes in 1 blocks
==33899== suppressed: 0 bytes in 0 blocks
==33899== Rerun with --leak-check=full to see details of leaked memory
==33899==
==33899== For lists of detected and suppressed errors, rerun with: -s
==33899== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 0 from 0)
关于realloc问题,这是我在tokenize函数中处理它的方式
#define BUFSIZE 64
#define DELIM " \t\r\n\a"
char **tokenize(char *line)
{
/*declaration of various fucntions*/
char **toks = malloc(sizeof(char *) * BUFSIZE);
int position = 0;
char *token, **token_backup;
int bufsize = BUFSIZE;
/*allocation error*/
if (toks == NULL)
{
free(toks);
perror("hsh");
}
token = strtok(line, DELIM);
/*Store token in toks*/
while (token != NULL)
{
toks[position] = token;
position++;
/*not enough memory*/
if (position >= BUFSIZE)
{
bufsize += BUFSIZE;
token_backup = toks;
toks = realloc(toks, position * sizeof(char *));
if (toks == NULL)
{
free(token_backup);
printf("allocation error\n");
exit(EXIT_FAILURE);
}
}
token = strtok(NULL, DELIM);
}
toks[position] = NULL;
return (toks);
}
4条答案
按热度按时间svdrlsy41#
你没有内存泄漏。你正在释放已经释放的内存。
每个
args[i]
都是指向line
内部某处的指针,它们不是单独分配的。因此,摆脱循环和 * 只有 * 免费的
args
和line
。zy1mlcev2#
我想这句台词
应该是
并且应当相应地声明
eof
。des4xlb03#
我的猜测是正确的,你正在使用strtok。strtok将返回指向输入缓冲区的指针。所以
argv[0]
与line
相同。所以你实际上删除了line
两次kse8i1jr4#
tokenize
函数不分配它返回的已分配数组中的单个字符串,这解释了line
是如何被释放两次的:当i
为0
且free(line)
位于main
的末尾时,free(args[i])
。此外,如果该行包含多个单词或以空格开头,则调用free
时使用的指针指向已分配块内部,这具有未定义的行为。tokenize
函数也有问题:bufsize * sizeof(char *)
而不是position * sizeof(char *)
。以下是修改后的版本: