malloc和free的帮助:Glibc检测到:free():无效指针
我需要调试这段代码的帮助。我知道问题出在malloc和free中,但找不到确切的位置、原因和解决方法。请不要回答:“使用gdb”,仅此而已。我会使用gdb来调试它,但我仍然不太了解它,并且仍在学习它,同时我希望有另一个解决方案 谢谢malloc和free的帮助:Glibc检测到:free():无效指针,c,memory-management,free,malloc,C,Memory Management,Free,Malloc,我需要调试这段代码的帮助。我知道问题出在malloc和free中,但找不到确切的位置、原因和解决方法。请不要回答:“使用gdb”,仅此而已。我会使用gdb来调试它,但我仍然不太了解它,并且仍在学习它,同时我希望有另一个解决方案 谢谢 #include <stdio.h> #include <stdlib.h> #include <ctype.h> #include <unistd.h> #include <string.h> #incl
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include <unistd.h>
#include <string.h>
#include <sys/wait.h>
#include <sys/types.h>
#define MAX_COMMAND_LENGTH 256
#define MAX_ARGS_NUMBER 128
#define MAX_HISTORY_NUMBER 100
#define PROMPT ">>> "
int num_elems;
typedef enum {false, true} bool;
typedef struct {
char **arg;
char *infile;
char *outfile;
int background;
} Command_Info;
int parse_cmd(char *cmd_line, Command_Info *cmd_info)
{
char *arg;
char *args[MAX_ARGS_NUMBER];
int i = 0;
arg = strtok(cmd_line, " ");
while (arg != NULL) {
args[i] = arg;
arg = strtok(NULL, " ");
i++;
}
num_elems = i;precisa em free_mem
if (num_elems == 0)
return 0;
cmd_info->arg = (char **) ( malloc(num_elems * sizeof(char *)) );
cmd_info->infile = NULL;
cmd_info->outfile = NULL;
cmd_info->background = 0;
bool b_infile = false;
bool b_outfile = false;
int iarg = 0;
for (i = 0; i < num_elems; i++)
{
if ( !strcmp(args[i], "<") )
{
if ( b_infile || i == num_elems-1 || !strcmp(args[i+1], "<") || !strcmp(args[i+1], ">") || !strcmp(args[i+1], "&") )
return -1;
i++;
cmd_info->infile = malloc(strlen(args[i]) * sizeof(char));
strcpy(cmd_info->infile, args[i]);
b_infile = true;
}
else if (!strcmp(args[i], ">"))
{
if ( b_outfile || i == num_elems-1 || !strcmp(args[i+1], ">") || !strcmp(args[i+1], "<") || !strcmp(args[i+1], "&") )
return -1;
i++;
cmd_info->outfile = malloc(strlen(args[i]) * sizeof(char));
strcpy(cmd_info->outfile, args[i]);
b_outfile = true;
}
else if (!strcmp(args[i], "&"))
{
if ( i == 0 || i != num_elems-1 || cmd_info->background )
return -1;
cmd_info->background = true;
}
else
{
cmd_info->arg[iarg] = malloc(strlen(args[i]) * sizeof(char));
strcpy(cmd_info->arg[iarg], args[i]);
iarg++;
}
}
cmd_info->arg[iarg] = NULL;
return 0;
}
void print_cmd(Command_Info *cmd_info)
{
int i;
for (i = 0; cmd_info->arg[i] != NULL; i++)
printf("arg[%d]=\"%s\"\n", i, cmd_info->arg[i]);
printf("arg[%d]=\"%s\"\n", i, cmd_info->arg[i]);
printf("infile=\"%s\"\n", cmd_info->infile);
printf("outfile=\"%s\"\n", cmd_info->outfile);
printf("background=\"%d\"\n", cmd_info->background);
}
void get_cmd(char* str)
{
fgets(str, MAX_COMMAND_LENGTH, stdin);
str[strlen(str)-1] = '\0';
}
pid_t exec_simple(Command_Info *cmd_info)
{
pid_t pid = fork();
if (pid < 0)
{
perror("Fork Error");
return -1;
}
if (pid == 0)
{
if ( (execvp(cmd_info->arg[0], cmd_info->arg)) == -1)
{
perror(cmd_info->arg[0]);
exit(1);
}
}
return pid;
}
void type_prompt(void)
{
printf("%s", PROMPT);
}
void syntax_error(void)
{
printf("msh syntax error\n");
}
void free_mem(Command_Info *cmd_info)
{
int i;
for (i = 0; cmd_info->arg[i] != NULL; i++)
free(cmd_info->arg[i]);
free(cmd_info->arg);
free(cmd_info->infile);
free(cmd_info->outfile);
}
int main(int argc, char* argv[])
{
char cmd_line[MAX_COMMAND_LENGTH];
Command_Info cmd_info;
//char* history[MAX_HISTORY_NUMBER];
while (true)
{
type_prompt();
get_cmd(cmd_line);
if ( parse_cmd(cmd_line, &cmd_info) == -1)
{
syntax_error();
continue;
}
if (!strcmp(cmd_line, ""))
continue;
if (!strcmp(cmd_info.arg[0], "exit"))
exit(0);
pid_t pid = exec_simple(&cmd_info);
waitpid(pid, NULL, 0);
free_mem(&cmd_info);
}
return 0;
}
#包括
#包括
#包括
#包括
#包括
#包括
#包括
#定义最大命令长度256
#定义最大参数数128
#定义最大历史编号100
#定义提示“>>>”
整数元素;
typedef枚举{false,true}bool;
类型定义结构{
字符**arg;
字符*填充;
字符*输出文件;
int背景;
}命令信息;
int parse_cmd(字符*cmd_行,命令信息*cmd_信息)
{
char*arg;
char*args[最大args\u编号];
int i=0;
arg=strtok(命令行“”);
while(arg!=NULL){
args[i]=arg;
arg=strtok(空,“”);
i++;
}
num_elems=i;precisa em free_mem
if(num_elems==0)
返回0;
cmd_info->arg=(char**)(malloc(num_elems*sizeof(char*));
cmd_info->infle=NULL;
cmd_info->outfile=NULL;
cmd_info->background=0;
bool b_infle=false;
bool b_outfile=false;
int iarg=0;
对于(i=0;i 如果(b_outfile | | i==num_elems-1 | | |!strcmp(args[i+1],“>”)| |!strcmp(args[i+1],“当您为cmd_info->infle
动态分配内存时,如下所示:
cmd_info->infile = malloc(strlen(args[i]) * sizeof(char));
您没有为终止的null
char分配空间
分配cmd\u info->outfile
当您为n
char分配空间并将长度为n
的字符串复制到其中时,我认为这会覆盖malloc
在数组末尾维护的元数据,当您调用free
以释放内存时会出现此错误,因为free没有找到元数据
编辑:
更改:
num_elems = i;
到
因为您正在用NULL
cmd_info->arg[iarg] = NULL;
您需要为此分配空间。因为C中的字符串以null结尾,所以它们在内存中的实际大小是length+1,而不是
cmd_info->infile = malloc(strlen(args[i]) * sizeof(char));
你应该
cmd_info->infile = malloc((strlen(args[i])+1) * sizeof(char));
编辑:正如Aeth所说,您需要更改malloc的每一次出现,以包含额外空字符的空间:
cmd_info->arg = (char **) ( malloc(num_elems * sizeof(char *)) ); //this one can stay, since it determines number of strings, not string length
cmd_info->outfile = malloc((strlen(args[i])+1) * sizeof(char));
cmd_info->arg[iarg] = malloc((strlen(args[i])+1) * sizeof(char));
您需要为每个字符串分配一个额外的char
,以处理终止null
cmd_info->arg[iarg]=malloc((strlen(args[i])+1)*sizeof(char))
您需要在cmd\u info->arg
数组中分配一个额外的char*
。这个额外的元素将存储表示参数数组结束的NULL
cmd_info->arg=(char**)(malloc((num_elems+1)*sizeof(char*))
我已在我的系统上确认,在进行了列出的两项更改后,程序成功释放了其所有内存,没有任何错误。通常,此错误通常是由于在malloc()
'd块外写入数据(在末尾或开头之前)。这可能会损坏内存分配器的内部簿记结构
其他人已经指出了您的代码中的特定问题。在代码隐藏得更深的情况下,我发现它对调试非常有用。以明显的代码减速为代价,它能够检测非法内存访问(以“无效读取”和“无效写入”的形式)在非常细粒度的级别上,内存调试器(如)也会很有帮助,并且不会带来太多开销,但根据我的经验,在查找所有内容方面不如Valgrind好
Valgrind在其“memcheck”模式下,将输出内存访问错误,并在程序中的堆栈跟踪中显示它们发生的位置。通常,当我在free()中出现“无效指针”错误时
,它将在某个时候被memcheck将发现的无效写入所取代。您从哪里得到错误?它没有说在哪一行…我已经更改了,但仍然得到相同的错误。我做错了什么?请帮助。编辑了问题。查看并查看在执行第二个s后是否仍然有相同的问题步骤+1,是的,这两个更改应该可以修复程序。好的发现:)
cmd_info->arg = (char **) ( malloc(num_elems * sizeof(char *)) ); //this one can stay, since it determines number of strings, not string length
cmd_info->outfile = malloc((strlen(args[i])+1) * sizeof(char));
cmd_info->arg[iarg] = malloc((strlen(args[i])+1) * sizeof(char));