Der*_*den 6 c valgrind memory-leaks memory-management
好的,首先,公平警告,这是一个班级的项目.除了修复我的内存泄漏之外,我不是在寻找任何帮助.我想我已经在这个C代码的空间上遵循了一些可怕的编码实践.无论如何,当我运行Valgrind来搜索内存泄漏发生的位置时,我一点都不清楚我错过了什么内存泄漏.我知道至少有两个字符串,我没有释放,但我malloc()编辑,纯粹基于valgrind输出的大小.因为我从项目中获取了一些无关的代码,valgrind行号很可能已经关闭,因此为了方便起见,我将它们标记为注释.
一点背景,我正在编写shell的基本功能.它目前执行以下操作:
1.接受用户输入
2.将输入解析为cmdin结构
3.执行命令,前提是它没有管道.
4.从我创建的cmdin中取出空间,然后从步骤1重新开始.这就是问题发生的地方.
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/wait.h>
#define MAX_SIZE 1024
#define MAX_CLEN 2097152
#define READ_END 0
#define WRITE_END 1
#define CHILD_STATUS 0
struct cmdin
{
char *cmd;
char **args;
int nargs;
int pipeflag;
};
//check if the last argument of the command passed to it is a pipe.
//if so, return the position of the pipe, otherwise, return 0
//if it has already found a pipe, it will return the position of that pipe
int conpipe(struct cmdin * cmd)
{
if(!cmd->pipeflag)
{
if(!strcmp(cmd->args[cmd->nargs], "|"))
{
return cmd->nargs;
}
else
{
return 0;
/* PROBLEM LINE BELOW */
} // line 46, where valgrind claims one of the problems exists
}
else
{
//printf("pipeflag: %d\n", cmd->pipeflag);
return (cmd->pipeflag);
}
}
//free the command after each runthrough
int freeze(struct cmdin cmd)
{
int i;
for(i=0; i <= (cmd.nargs); i++)
{
//printf("cmd.args[%d]: %s\n",i, cmd.args[i]);
/* PROBLEM LINE BELOW*/
free(cmd.args[i]); //this is line 62, as noted by valgrind
}
free(cmd.args);
free(cmd.cmd);
return 0;
}
//parse input, and add a null to the end
struct cmdin * parse(char *cmd)
{
//allocate space for the command
struct cmdin *ped = malloc(sizeof(struct cmdin));
//declare pipeflag, and nargs as 0
ped->pipeflag = 0;
ped->nargs = 0;
//allocate space for the array of strings, and for the string cmd.
ped->args = malloc(sizeof(char*) * MAX_SIZE);
ped->cmd = malloc(sizeof(char) * MAX_SIZE);
//scan the input, and put the first argument into the cmd string
sscanf(cmd, "%s %[^\n]", ped->cmd, cmd);
//allocate space for the next string, and then copy cmd to it.
ped->args[ped->nargs] = malloc(sizeof(char) * MAX_SIZE);
strcpy(ped->args[ped->nargs], ped->cmd);
ped->pipeflag = conpipe(ped);
/* PROBLEM LINE BELOW*/
ped->nargs++; // line 86, where valgrind claims the second leak is called?
ped->args[ped->nargs] = malloc(sizeof(char) * MAX_SIZE);
//loop that allocates space for a command, and then assigns
//the next arg to it.
while(sscanf(cmd, " %s %[^\n]", ped->args[ped->nargs], cmd) == 2)
{
ped->pipeflag = conpipe(ped);
ped->nargs++;
ped->args[ped->nargs] = malloc(sizeof(char) * MAX_SIZE);
}
strncpy(ped->args[ped->nargs], cmd, strlen(cmd)-1);
ped->nargs++;
//ped->args[ped->nargs] = malloc(sizeof(char) * MAX_SIZE);
ped->args[ped->nargs] = NULL;
return ped;
}
int main()
{
char cwd[MAX_CLEN];
getcwd(cwd, sizeof(cwd));
char input[MAX_CLEN];
char *exit = "exit\n";
char *cd = "cd";
//Command to take input
printf("tosh$ ");
fgets(input, sizeof input, stdin);
while(strcmp(input, exit))
{
//Command to parse input
struct cmdin *cmd;
cmd = parse(input);
//if there is not a pipeflag
if(!cmd->pipeflag)
{
//Change directories
if(!strcmp(cd, cmd->args[0]))
{
chdir(cmd->args[1]);
getcwd(cwd, sizeof(cwd));
}
else if(strcmp(input, exit))
{
//command to run input
int child_pid;
child_pid = fork();
if(child_pid == 0)
{
if(strcmp(cmd->args[1],cmd->args[0]))
{
execvp(cmd->cmd, cmd->args);
}
else
{
free(cmd->args[1]);
cmd->args[1] = NULL;
cmd->nargs--;
execvp(cmd->cmd, cmd->args);
}
}
else
{
wait(&child_pid);
}
}
freeze(*cmd);
free(cmd);
}
//Command to take input
printf("tosh$ ");
fgets(input, sizeof input, stdin);
}
return 0;
}
Run Code Online (Sandbox Code Playgroud)
注意:这个valgrind的输入,如下所示:
tosh$ ls -al
tosh$ exit
Run Code Online (Sandbox Code Playgroud)
valgrind Heap和Leak Summaries如下:
HEAP SUMMARY:
==4901== in use at exit: 4,096 bytes in 2 blocks
==4901== total heap usage: 6 allocs, 4 frees, 24,600 bytes allocated
==4901==
==4901== 2,048 bytes in 1 blocks are definitely lost in loss record 1 of 2
==4901== at 0x4C2B3F8: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==4901== by 0x400A48: parse (tosh.c:46)
==4901== by 0x400C97: main (tosh.c:86)
==4901==
==4901== 2,048 bytes in 1 blocks are definitely lost in loss record 2 of 2
==4901== at 0x4C2B3F8: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==4901== by 0x400BDE: parse (tosh.c:62)
==4901== by 0x400C97: main (tosh.c:86)
==4901==
==4901== LEAK SUMMARY:
==4901== definitely lost: 4,096 bytes in 2 blocks
==4901== indirectly lost: 0 bytes in 0 blocks
==4901== possibly lost: 0 bytes in 0 blocks
==4901== still reachable: 0 bytes in 0 blocks
==4901== suppressed: 0 bytes in 0 blocks
Run Code Online (Sandbox Code Playgroud)
更新:根据要求.我的Makefile:
CC=gcc
CFLAGS=-g -Wall
TARGET=tosh
$(TARGET): $(TARGET).c
$(CC) $(CFLAGS) -o $(TARGET) $(TARGET).c
Run Code Online (Sandbox Code Playgroud)
Valgrind版本:valgrind-3.7.0
gcc版本:gcc(Ubuntu/Linaro 4.7.2-2ubuntu1)4.7.2
echo $ LD_PRELOAD:
(这没什么打印)
没有成功重现。但有几点注意事项。
\n\n使用可用的错误和警告。
\n\ngcc -Wall -Wextra -pedantic \xe2\x80\xa6\nRun Code Online (Sandbox Code Playgroud)检查返回值和操作是否成功。这对于减少错误至关重要,尤其是那些只有一英里后的用户案例才会发现的错误。
if (!(foo = malloc(size))) {\n perror("mem");\n}\n\n...\n\n\n/* This line is no good: */\nsscanf(cmd, "%s %[^\\n]", ped->cmd, cmd);\n/* | |\n * +----------+----------------+\n * |\n * +--- Not good. UB. (Input / Output same.)\n */\nRun Code Online (Sandbox Code Playgroud)\n\n您可以添加一个例程来获取数量和尺寸......
\n\ni = sscanf(cmd, "%s%n %[^\\n]%n", ped->cmd, &n1, cmd, &n2);\n\nif (i < 2) {\n /* Debug print. */\n fprintf(stderr, \n "%s:%-3d; "\n "sscanf => %d items and %d bytes str[%d]<%s>\\n", \n __FILE__, __LINENO_,\n i, n2, n1, ped->cmd\n );\n}\nRun Code Online (Sandbox Code Playgroud)\n\nETC。
\n| 归档时间: |
|
| 查看次数: |
617 次 |
| 最近记录: |