C 当我尝试释放动态分配的指针数组时,Valgrind抛出无效的free()
我正在分配一个动态分配的指针数组,并试图在程序结束时释放它们。问题是我总是在valgrind上得到一个“invalid free()”错误,尽管我真的找不到哪里出了问题。 例如:我正在使用malloc为argv[0]和argv分配内存,然后尝试在For循环中释放它们。 我使用以下方法分配指针数组:C 当我尝试释放动态分配的指针数组时,Valgrind抛出无效的free(),c,arrays,unix,malloc,free,C,Arrays,Unix,Malloc,Free,我正在分配一个动态分配的指针数组,并试图在程序结束时释放它们。问题是我总是在valgrind上得到一个“invalid free()”错误,尽管我真的找不到哪里出了问题。 例如:我正在使用malloc为argv[0]和argv分配内存,然后尝试在For循环中释放它们。 我使用以下方法分配指针数组: char ucom[10], bin[15] = "/bin/"; char* str = (char *) malloc(MAX_LINE_LENGTH*sizeof(char)); char**
char ucom[10], bin[15] = "/bin/";
char* str = (char *) malloc(MAX_LINE_LENGTH*sizeof(char));
char** argv = (char **) malloc(sizeof(char*)); //ALLOCATING MEMORY FOR ARGV
int status, i = 0;
printf("Shell2$**");
strcpy(bin, "/bin/");
fgets(str, MAX_LINE_LENGTH, stdin);
char *token;
token = strsep(&str, " ");
while(token != NULL && i < 4){
if(token[strlen(token)-1] == '\n')
token[strlen(token)-1] = '\0';
argv[i] = (char *) malloc(MAX_ARGUMENT_LENGTH*sizeof(char)); //ALLOCATING MEMORY FOR POINTERS INSIDE ARGV, running two times in my example
printf("\n\nI:%d\n\n",i);
if(argv[i] == NULL) printf("Memory Allocation Problem");
argv[i] = token;
token = strsep(&str, " ");
i++;
argv = (char **)realloc(argv, (i+2)*sizeof(char*));
}
char-ucom[10],bin[15]=“/bin/”;
char*str=(char*)malloc(最大行长*sizeof(char));
char**argv=(char**)malloc(sizeof(char*))//为ARGV分配内存
int状态,i=0;
printf(“Shell2$**”);
strcpy(bin,“/bin/”);
fgets(str,最大线长度,标准尺寸);
字符*令牌;
标记=strep(&str,“”);
while(令牌!=NULL&&i<4){
if(令牌[strlen(令牌)-1]=='\n')
令牌[strlen(令牌)-1]='\0';
argv[i]=(char*)malloc(MAX_ARGUMENT_LENGTH*sizeof(char));//为argv内部的指针分配内存,在我的示例中运行了两次
printf(“\n\nI:%d\n\n”,i);
if(argv[i]==NULL)printf(“内存分配问题”);
argv[i]=令牌;
标记=strep(&str,“”);
i++;
argv=(char**)realloc(argv,(i+2)*sizeof(char*);
}
然后我试着释放他们:
wait(&status);
for(int f = 0; f < i; f++){
if(argv[f] != NULL)
free(argv[f]); //Free runs two times as the number of time malloc has been called, but fails at the second free.
}
free(str);
free(argv);
wait(&status);
对于(int f=0;f
在我的示例中,虽然malloc运行了2次,为argv[0]和argv分配了内存,但当结束处的for循环尝试释放argv时,它失败了,valgrind说这是一个无效的释放,但它成功地释放了argv[0]
提前谢谢大家
valgrind的输出:
错误不仅仅是@Fredrarson和我已经指出的 函数
strep()
实际上修改了传递给它的指针,因此char*token=strep(&str,“”)
更改指针。由于str
是从malloc
获取的,因此无法正确释放它
如果要在malloc的内存中调用strep()
,必须保存原始指针的副本,并在最后释放它
另外,不是严格可移植但高度可用的函数strdup()
对于制作字符串的副本非常有用,因此,与其分配一堆内存,然后将字符串复制到其中,您只需strdup()
该字符串(稍后释放它)
就我所知,这消除了许多安全问题的复杂性。除了@Fredrarson和我已经指出的问题之外,还有更多的问题 函数
strep()
实际上修改了传递给它的指针,因此char*token=strep(&str,“”)
更改指针。由于str
是从malloc
获取的,因此无法正确释放它
如果要在malloc的内存中调用strep()
,必须保存原始指针的副本,并在最后释放它
另外,不是严格可移植但高度可用的函数strdup()
对于制作字符串的副本非常有用,因此,与其分配一堆内存,然后将字符串复制到其中,您只需strdup()
该字符串(稍后释放它)
就我所知,这消除了许多安全问题的复杂性。请提供一个详细的说明。尝试对不完整的代码进行注释是没有效果的,因为问题甚至可能不在您所展示的部分中。例如,分配代码是否在函数中?一个常见的错误是将内存分配给本地作用域变量,并在调用者中释放内存。但我们无法从您的不完整代码中判断情况是否如此。因此,我们总是要求提供一个最小的可验证示例。
argv[i]=token代码>--oops,您刚刚完成了两行之前的内存分配。也许你的意思是strcpy(argv[i],token)代码>?您的argv
数组以一个元素开始,每个循环扩展一个指针,因此它总是比参数多一个项目(这是合理的),但最后一个指针不会被置空。建议argv[i]=NULL代码>在while循环之后。我可以要求您编辑并减少不必要的缩进吗?这将提高可读性,特别是对于那些通过移动设备(如我)阅读的人。你需要将Valgrind的输出作为文本包含在问题中。请提供一个答案。尝试对不完整的代码进行注释是没有效果的,因为问题甚至可能不在您所展示的部分中。例如,分配代码是否在函数中?一个常见的错误是将内存分配给本地作用域变量,并在调用者中释放内存。但我们无法从您的不完整代码中判断情况是否如此。因此,我们总是要求提供一个最小的可验证示例。argv[i]=token代码>--oops,您刚刚完成了两行之前的内存分配。也许你的意思是strcpy(argv[i],token)代码>?您的argv
数组以一个元素开始,每个循环扩展一个指针,因此它总是比参数多一个项目(这是合理的),但最后一个指针不会被置空。建议argv[i]=NULL代码>在while循环之后。我可以要求您编辑并减少不必要的缩进吗?这将提高可读性,特别是对于那些通过移动设备(如我)阅读的人来说。你需要将Valgrind的输出作为文本包含在问题中。
#define _BSD_SOURCE // for strsep
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#define MAX_LINE_LENGTH 80
#define MAX_ARGUMENT_LENGTH 10 // made up numbers
int main()
{
char *str = malloc(MAX_LINE_LENGTH);
char *str_save = str;
char **argv = malloc(sizeof(char*)); //ALLOCATING MEMORY FOR ARGV
int i = 0;
printf("Shell2$**"); fflush(stdout); // make sure user sees the prompt
strcpy(bin, "/bin/");
fgets(str, MAX_LINE_LENGTH, stdin);
char *token;
while ( (token = strsep(&str, " ")) != NULL && i < 4 )
{
if(token[strlen(token)-1] == '\n')
token[strlen(token)-1] = '\0';
argv[i] = strdup(token);
if(argv[i] == NULL) printf("Memory Allocation Problem");
i++;
argv = realloc(argv, i * sizeof(char*));
}
argv[i] = NULL; // GOOD IDEA TO ADD THIS
// run the shell
// wait(&status);
for(int f = 0; f < i; f++){
if(argv[f] != NULL)
free(argv[f]);
}
free(str_save);
free(argv);
}
#define _BSD_SOURCE // for strsep
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#define MAX_LINE_LENGTH 80
int main()
{
char **argv = malloc(sizeof(char*)); //ALLOCATING MEMORY FOR ARGV
int i = 0;
printf("Shell2$**"); fflush(stdout); // make sure user sees the prompt
char linebuf[MAX_LINE_LENGTH];
fgets(linebuf, sizeof linebuf, stdin);
char *token;
char *str = linebuf;
while ( (token = strsep(&str, " ")) != NULL && i < 4 )
{
if (token[strlen(token)-1] == '\n')
token[strlen(token)-1] = '\0';
argv[i++] = token;
argv = realloc(argv, i * sizeof(char*));
}
argv[i] = NULL; // GOOD IDEA TO ADD THIS
// run the shell
// wait(&status);
free(argv);
}