【问题标题】:program crashes while using realloc使用 realloc 时程序崩溃
【发布时间】:2016-04-17 13:01:53
【问题描述】:

给了我一个未知大小的文本文件,我必须读到最后,计算单词、字母和其他一些东西的数量。为此,我尝试读取整个文件并将所有单词保存在一个数组中。我被告知要使用动态内存分配,因为我事先不知道文本文件的大小。

在我进入计算单词和字母的算法之前,我试图让动态内存分配工作。这是我的代码:

int main(int argc, char *argv[]) {

    FILE *fp; // file pointer

    //defining a dynamic string array

    char **array = malloc(10 * sizeof(char *)); //10 rows for now, will be   dynamically changed later

    int i,size = 10, current = 0; // current points to the position of the next slot to be filled

    for(i=0; i<10; i++){
        array[i] = malloc(20); //the max word size will be 20 characters (char size = 1 byte)
    }


    fillArray(fp, array, current, size);

    return 0;
}

我定义了一个字符串数组,一个显示其大小的变量,以及一个指向将添加下一个元素的槽的变量。 功能如下:

int fillArray(FILE *fp, char **p, int ptr, int size){

    puts("What's the name of the file (and format) to be accessed?\n (It has to be in the same directory as the program)");
    char str[20];
    gets(str);  //getting the answer
    fp = fopen((const char *)str, "r"); //opening file


    int x=0, i=0, j;

    while(x!=EOF){ // looping till we reach the end of the file
        printf("current size: %d , next slot: %d\n", size, ptr);
        if(ptr>=size){
            printf("increasing size\n");
            addSpace(p, &size);
        }
        x = fscanf(fp, "%19s", p[i]);
        puts(p[i]);
        i++;
        ptr++;
    }

}

void addSpace(char **p, int *size){ //remember to pass &size
    //each time this is called, 10 more rows are added to the array
    p = realloc(p,*size + 10);
    int i;
    for(i=*size; i<(*size)+10; i++){
        p[i] = malloc(20);
    }
    *size += 10;
}

void freeSpace(char **p, int ptr){
    //each time this is called, the rows are reduced so that they exactly fit the content
    p = realloc(p, ptr); //remember that ptr points to the position of the last occupied slot + 1

}

一开始,数组的行数是 10。每次文本的单词不适合数组时,调用函数addSpace 再增加 10 行。程序运行成功 3 次(达到 30 行)然后崩溃。

在使用 printf 找出程序崩溃的位置后(因为我还不习惯调试器),它似乎在尝试添加 10 行(至 40 行)时崩溃了。我无法弄清楚问题或如何解决它。任何帮助表示赞赏。

【问题讨论】:

  • 如果你malloc(20),最大字符串长度为19个字符;第 20 个字符将是 \0。你也应该重新分配*size + 10 * sizeof *p
  • 'addSpace(p, &size);'不能修改'p',如果它是一个重新分配的指针,这是一个大问题:(

标签: c arrays malloc realloc


【解决方案1】:

C 是按值传递的。指针p 被传递给addSpace(p, &amp;size);,并在函数中创建该指针的副本。更改副本后:p = realloc(p,*size + 10); 原件保持不变。

在 realloc 调用之后,原始指针不再有效。使用它会导致未定义的行为,在您的情况下会崩溃。

返回新值并赋值给原指针:

p = addSpace( p , &size );

【讨论】:

  • 但是已经成功了2次了,如果是这样的话,那应该是不行了吧?
  • @Alan 不,正常工作是未定义行为的结果之一。
  • @Alan 交付它/交它/不管它,然后它就会坏掉。 UB就是这样的恶意:(
【解决方案2】:

经典!

您还传递了一个双指针reallocd,调用者和被调用者之间的地址已更改。

还有一个realloc 问题。

p = realloc(p,*size + 10);

如果realloc 失败,指向内存块的原始指针被破坏。

正确的做法:

char **tmp_ptr = realloc(p, *size + 10);
if (tmp_ptr == NULL){
   perror("Out of memory");
}else{
    p = tmp_ptr;
}
return p;

你可以用另一种方式来做,要么返回新块的地址,要么使用三重指针。

void addSpace(char ***p, int *size){ //remember to pass &size
    //each time this is called, 10 more rows are added to the array
    char **tmp_ptr = realloc(*p, *size + 10);
    if (tmp_ptr == NULL){
       perror("Out of memory");
    }else{
        *p = tmp_ptr;
    }
    int i;
    for(i=*size; i<(*size)+10; i++){
        *p[i] = malloc(20);
    }
    *size += 10;
}

来自调用者

addSpace(&p, &size);

【讨论】:

  • 哦,比那差多了:(
  • @MartinJames 发现它有点晚了...... soz!
  • 但这意味着我不能再阅读任何单词了,对吧?然而,该文件包含 70 个单词,并且可能更多。没有办法可以全部添加吗?
  • @Alan 当然。通过地址传递“p”,或者更友好地,从 addSpace() 中返回 p 而不是 void。
  • @t0mm13b 如果可以的话,一件事。如果我要返回指针,那么函数声明应该是char **addSpace(...) 对吗?因为我收到conflicting types 错误
猜你喜欢
  • 1970-01-01
  • 2018-12-22
  • 1970-01-01
  • 1970-01-01
  • 2015-06-28
  • 1970-01-01
  • 2017-03-26
  • 2018-09-13
  • 2012-03-05
相关资源
最近更新 更多