Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/arrays/14.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C 当我尝试释放动态分配的指针数组时,Valgrind抛出无效的free()_C_Arrays_Unix_Malloc_Free - Fatal编程技术网

C 当我尝试释放动态分配的指针数组时,Valgrind抛出无效的free()

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**

我正在分配一个动态分配的指针数组,并试图在程序结束时释放它们。问题是我总是在valgrind上得到一个“invalid free()”错误,尽管我真的找不到哪里出了问题。 例如:我正在使用malloc为argv[0]和argv分配内存,然后尝试在For循环中释放它们。 我使用以下方法分配指针数组:

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);
}