【问题标题】:realloc invalid old sizerealloc 无效的旧大小
【发布时间】:2012-07-09 12:23:14
【问题描述】:

免责声明:这是作业。我正在尝试,不希望或不希望任何人为我做这件事。只需指出我出错的地方(呵呵),将不胜感激。

作业要求我创建一个包含 10 个元素的 int* 数组,然后尝试在其中插入一百万个整数。每次插入都会检查数组是否需要调整大小,如果需要,我会增加它的大小以便它可以容纳更多元素。

当我插入 10,000 个元素时,它可以正常工作,但如果我尝试 100,000 个元素,我会收到以下错误:

*** glibc detected *** ./set2: realloc(): invalid old size: 0x00000000024dc010 ***

这是我正在运行的代码。我已经评论了它,所以它很容易阅读。

void main()
{
    //begin with a size of 10
    int currentsize = 10;
    int* arr = malloc(currentsize * sizeof(int));       
    int i;

    //initalize with all elements set to INT_MAX
    for(i = 0; i < currentsize; i++) {
        arr[i] = INT_MAX;
    }


    // insert random elements
    for(i = 0; i < 100000; i++) {
        currentsize = add(rand() % 100,arr,currentsize);
    }

    free(arr);
}

/*
    Method resizes array if needed, and returns the new size of the array
    Also inserts the element into the array
*/
int add(int x, int* arr, int size)
{
    //find the first available location 
    int newSize = size;
    int i;
    for(i = 0; i < size; i++) {
        if (arr[i] == INT_MAX)
            break;
    }

    if (i >= size) {
        //need to realloc
        newSize++;
        arr = realloc(arr, newSize * sizeof(int) );     
    }

    arr[i] = x;

    return newSize;
}

【问题讨论】:

    标签: c pointers malloc realloc


    【解决方案1】:

    这个错误可能是因为你在函数add中正确使用realloc改变了arr,但是当add返回时这个修改值丢失了。所以下一次对add 的调用将收到旧的,现在是错误的值。

    另外,我不明白您为什么要使用 for 循环进行搜索。您知道要在最后一个元素处添加,那么为什么要搜索呢?只需重新分配数组并将新值插入新插槽即可。

    顺便说一句,我很确定您的老师正试图让您看到重新分配每个成员会导致渐近运行时间问题。 realloc 的大多数实现将使用此算法进行大量复制。这就是为什么真正的程序会以大于 1(通常为 1.5 或 2)而不是固定数量的因子来增加数组大小。

    通常的习惯用法是将可变大小的数组抽象成一个结构体:

    typedef struct array_s {
      int *elts;
      int size;
    } VARIABLE_ARRAY;
    
    void init(VARIABLE_ARRAY *a)
    {
      a->size = 10;
      a->elts = malloc(a->size * sizeof a->elts[0]);
      // CHECK FOR NULL RETURN FROM malloc() HERE
    }
    
    void ensure_size(VARIABLE_ARRAY *a, size_t size) 
    {
      if (a->size < size) {
    
        // RESET size HERE TO INCREASE BY FACTOR OF OLD SIZE
        // size = 2 * a->size;
    
        a->elts = realloc(size * sizeof a->elts[0]);
        a->size = size;
    
        // CHECK FOR NULL RETURN FROM realloc() HERE
      }
    }
    
    // Set the i'th position of array a. If there wasn't
    // enough space, expand the array so there is.
    void set(VARIABLE_ARRAY *a, int i, int val)
    {
      ensure_size(a, i + 1);
      a->elts[i] = val;
    }
    
    void test(void)
    {
      VARIABLE_ARRAY a;
    
      init(&a);
    
      for (int i = 0; i < 100000; i++) {
        set(&a, i, rand());
      }
    
      ...
    
    }
    

    【讨论】:

    • 是否应该添加接收int** 才不会导致此问题?
    • 是的,你说你不想要答案,我尊重这一点。你是对的。
    • 您对老师让我们看到的内容是正确的。我们正在编写两个版本,一个以 2 倍增长重新分配,另一个以 1 倍增长。
    • 谢谢。你的帮助让我走了。我还不得不将我的作业更改为*(*arr + i)
    【解决方案2】:

    我会将arr 作为指针(指向指针)传递给add(),以便可以在add() 内部对其进行修改

    int add(int x, int** arr, int size)
    {
       // ...
       *arr = realloc(*arr, newSize * sizeof(int) );
    }
    

    并称它为....

    currentsize = add(rand() % 100, &arr, currentsize);
    

    请注意,您的代码(以及我建议的更改)没有进行任何错误检查。您应该检查mallocrealloc 的返回值是否为NULL

    【讨论】:

      猜你喜欢
      • 2014-08-26
      • 2015-02-05
      • 2012-02-02
      • 1970-01-01
      • 2019-10-26
      • 1970-01-01
      • 1970-01-01
      • 2017-02-19
      相关资源
      最近更新 更多