【问题标题】:realloc(): invalid next size in C [duplicate]realloc():C中的下一个大小无效[重复]
【发布时间】:2018-06-13 04:24:25
【问题描述】:

新年快乐!

一段时间以来,我一直在努力寻找导致错误的原因,我将在下面解释一段时间,我将非常感谢任何帮助。我有以下代码,原则上应该实现一个堆栈:

#include <stdio.h>
#include <stdlib.h>

void resize(int *nmax, int *d){
    int i, *u;
    *nmax *= 2;
    u = (int *)realloc(d,sizeof(int)*(*nmax));
    if(u == NULL){
        printf("Error!\n");
        exit(1);
    }
    d = u;
}

void push(int *n, int *d, int *nmax){
    int u = *n , i;
    if(u == *nmax) {
        resize(nmax, d);
    }
    *(d + u) = u;
    u++;
    *n = u;
}

void pop(int *n){
    int u = *n;
    *n = u - 1;
}

int main(){
    int *d, n = 0, i, nmax = 5;
    d = (int *)malloc(sizeof(int)*nmax);
    *(d+(n))= n;
    n++;
    *(d+(n)) = n;
    n++;
    *(d+(n)) = n;
    n++;
    //for(i = 0;i < n;i++)
        //printf("%d\n",*(d+i));
    push(&n,d, &nmax);
    push(&n,d, &nmax);
    push(&n,d, &nmax);
    push(&n,d, &nmax);
    push(&n,d, &nmax);
    push(&n,d, &nmax);
    push(&n,d, &nmax);
    push(&n,d, &nmax);
    push(&n,d, &nmax);
    push(&n,d, &nmax);
    push(&n,d, &nmax);
    push(&n,d, &nmax);
    push(&n,d, &nmax);
    push(&n,d, &nmax);
    //pop(&n);
    //pop(&n);
    //pop(&n);
    for(i = 0;i<n;i++)
        printf("%d\n",*(d+i));

    return 0;
}

它似乎表现正常,直到我在推送操作堆栈之前取消注释 printf 语句。我得到的错误是:

0
1
2
*** Error in `./a.out': realloc(): invalid next size: 0x0000000000f08010 ***

我不确定我是否已经解释过了,如果我没有解释清楚,请让我知道我可以添加的任何其他详细信息,以便更清楚地说明。

非常感谢您的帮助!

编辑:

希望代码现在变得更具可读性,这就是我所拥有的:

#include <stdio.h>
#include <stdlib.h>

void resize(int *sizeOfArray, int *myArray){
    int i, *u;
    *sizeOfArray *= 2;
    u = (int *)realloc(myArray,sizeof(int)*(*sizeOfArray));
    if(u == NULL){
        printf("Error!\n");
        exit(1);
    }
    myArray = u;
}

void push(int *pos, int *myArray, int *sizeOfArray){
    int i;
    if(*pos == *sizeOfArray) {
        resize(sizeOfArray, myArray);
    }
    *(myArray + (*pos)) = *pos;
    (*pos)++;
}

void pop(int *pos){
    (*pos)--;
}

int main(){
    int *myArray, pos = 0, i, sizeOfArray = 5;
    myArray = (int *)malloc(sizeof(int)*sizeOfArray);
    *(myArray + pos)= pos;
    pos++;
    *(myArray + pos) = pos;
    pos++;
    *(myArray + pos) = pos;
    pos++;
    //for(i = 0;i < pos;i++)
        //printf("%d\n",*(myArray+i));
    push(&pos, myArray, &sizeOfArray);
    push(&pos, myArray, &sizeOfArray);
    push(&pos, myArray, &sizeOfArray);
    push(&pos, myArray, &sizeOfArray);
    //pop(&pos);
    //pop(&pos);
    //pop(&pos);
    for(i = 0;i<pos;i++)
        printf("** %d\n",*(myArray+i));

    return 0;
}

现在,错误发生了变化——这可能表明该方法存在问题——它显示:

我应该得到:

** 0
** 1
** 2
** 3
** 4
** 5
** 6

相反,我得到:

** 0
** 0
** 2
** 3
** 4
** 5
** 6

为什么?只有当我取消注释中间的 printf 时,我才会得到这个。

感谢您的帮助。

【问题讨论】:

  • d = u; 仅更改传递给 resize 的本地值,然后被遗忘。
  • 一堆什么?由于无意义的标识符,此代码非常不清楚。 dnunmax 到底代表什么?您还使事情变得比必要的复杂得多(并且难以理解);例如所有那些显式的数组索引计算。为什么?
  • @WeatherVane 非常感谢您的帮助!但是,如果我在推送操作之前没有“printf-ing”,我会得到一个“正常”的行为(至少,我看到了我预期我应该看到的)。如果你的建议是怎么回事,我大部分时间不应该得到错误的结果吗?
  • @meaning-matters 非常感谢您的评论。一堆什么都没有。这是我自己做的一个练习。我改变了所有的 d、n、u、nmax,所以它们以某种方式反映了我想要它们成为的样子。我希望代码提高了可读性。无论如何,我同意你的观点。
  • @Jean-FrançoisFabre 谢谢!

标签: c stack realloc


【解决方案1】:

int *myArray 是你的函数的语言环境,myArray = u; 语句只会改变语言环境的值,而不是调用函数的值。

你必须使用双指针或返回值。

int *resize(int *sizeOfArray, int *myArray){
    *sizeOfArray *= 2;
    int *u = realloc(myArray, *sizeOfArray * sizeof *myArray);
    if (u == NULL) {
        printf("Error!\n");
        exit(1);
    }
    return u;
}

myArray = resize(sizeOfArray, myArray);

当然,您也必须在 push() 中更改此行为。

【讨论】:

  • 非常感谢!你的意思是我也应该做 int* push(...) 吗?
  • @moijoune 是的,你本质上是在包装realloc,所以表现得像realloc
  • 我认为当函数无法立即调用exit 时,这是个坏主意。当呼叫失败时,并不意味着整个过程应该结束。只需返回一个错误值(在这种情况下为NULL)并让用户决定要做什么。
  • @Pablo ΤΗΑΝΚ 你太棒了!!!是的,这就是解决问题的方法。我仍然感到有点困惑,中间的 printf 导致了这一切,但也许这是偶然的。我不确定为什么数组没有通过引用传递,这意味着更多的阅读。再次感谢您!
  • @moijoune 它造成了麻烦,因为它正在访问当时无效的内存。在您的实现中,realloc 可能返回了一个不同的指针,从而使原来的指针无效。访问这样一个无效的指针会产生未定义的行为,例如它可以打印一些数字但它也可能崩溃。 因为您的实现丢弃了新指针并保留了旧指针,发生了这种未定义的行为,在您的情况下,它会导致您的第一个版本崩溃,而第二个版本则导致垃圾。
猜你喜欢
  • 2011-02-25
  • 2012-10-31
  • 2013-09-28
  • 1970-01-01
  • 1970-01-01
  • 2014-10-13
  • 2020-12-27
相关资源
最近更新 更多