【问题标题】:Increase dynamic array size with a function; free error, invalid next size (fast)使用函数增加动态数组大小;免费错误,下一个尺寸无效(快速)
【发布时间】:2017-01-04 12:25:10
【问题描述】:

我需要创建一个动态数组并放入五个数字,然后再输入另一个输入,这就是我必须增加数组大小的数量。 当所有输入结束后,我将增加数组大小并将数字放入其中。

一切正常,但免费返回此错误:“free(): invalid next size (fast): 0x00000...”

我认为“扩展”函数内部存在错误

void extend(int *V, int n, int s)
{
    int *pt;
    pt = realloc(V, n*sizeof(int));
    int i;
    pt[5]=s;
    for(i=6;i<(5+n);i++)
        pt[i] = pt[i-1]*2;
}

int main()
{
    int *v;
    int n,i, sum;
    sum = 0;

    v = malloc(sizeof(int)*5);

    for(i=0;i<5;i++)
    {
        scanf("%d", &v[i]);
        sum+=v[i];
    }   

    scanf("%d", &n);

    extend(v,n,sum);

    for(i=0;i<(5+n);i++)
        printf("%d\n", v[i]);
    free(v);
    return 0;
}

【问题讨论】:

    标签: c arrays function pointers dynamic-arrays


    【解决方案1】:

    函数不会改变原来的变量v。它至少应该被定义为

    void extend(int **V, int n, int s)
    {
        int *pt;
        pt = realloc(*V, n*sizeof(int));
        if ( pt )
        {
            int i;
            pt[5]=s;
            for(i=6; i < n; i++)
            pt[i] = pt[i-1]*2;
            *V = pt; 
        }
    }
    

    或者

    int extend(int **V, int n, int s)
    {
        int *pt;
    
        pt = realloc(*V, n*sizeof(int));
        int success = pt != NULL;
    
        if ( success )
        {
            int i;
            pt[5]=s;
            for(i=6; i < n; i++)
            pt[i] = pt[i-1]*2;
            *V = pt; 
        }
    
        return success;
    }
    

    并且该函数应该被称为lije

    extend( &v,n,sum);
    

    考虑到函数是不安全的,因为一般n可以小于或等于5。而这个语句

    for(i=6;i<(5+n);i++)
              ^^^^
    

    可能导致未定义的行为。

    或者函数应该分配 n + 5 个元素。例如

        pt = realloc(*V, ( n + 5 )*sizeof(int));
                         ^^^^^^^^
    

    这个神奇的数字 5 的使用也不清楚,没有意义。

    【讨论】:

    • 我有一个包含 5 个元素的数组,“n”是一个数字,扩展函数应该将其他“n”个元素添加到包含 5 个元素的数组中。例如:数组[5],n = 3 -> 数组[8]
    • @user4789408 该函数分配了 n 个元素,但在循环中使用了 n + 5 个元素。
    • @user4789408 如果要扩展到 8 个元素,则必须将 n=8 传递给函数,而不是 n=3。 realloc() 获得新的大小。不是增量大小。
    • 我修改了代码,现在用“realloc(V, (5+n)*sizeof(int))”应该没问题吧?
    • @user4789408 这是个坏主意,因为现在你强迫其他人修改他们的答案。
    【解决方案2】:

    好吧,在函数extend

    • 您正在将pt 分配给n 条目的内存块
    • 您正试图在超出n-1 的索引处访问pt

    更具体地说,使用:

    pt = realloc(V, n*sizeof(int));
    for (i=6; i<(5+n); i++)
        pt[i] = ...
    

    您正在执行非法的内存访问操作:

    • pt[n]
    • pt[n+1]
    • pt[n+2]
    • pt[n+3]
    • pt[n+4]

    【讨论】:

    • 你的答案是正确的,这解决了问题,但现在我知道为什么输出是正确的了?
    • @user4789408:我不明白“现在我会知道为什么输出是正确的”......这是个问题吗???
    • 如果我在 pt[n], pt[n+1] 上执行非法内存访问操作,为什么在 Main 的末尾输出是正确的?
    • 这是未定义的行为。而 undefined 真的意味着任何事情都可能发生。甚至打印您的预期结果也可能发生。并非每次访问非法内存位置都会导致分段错误。
    【解决方案3】:

    realloc 返回一个指向新内存块的指针,但您不会将它返回给调用者。相反, main 中的 v 与调用之前的 v 相同,但现在无效,这无疑会导致您的错误,最简单的方法是返回 pt:

    int* extend(int *V, int n, int s)
    {
        int *pt;
        pt = realloc(V, n*sizeof(int));
        int i;
        pt[5]=s;
        for(i=6;i<(5+n);i++)
        pt[i] = pt[i-1]*2;
        return pt;
    }
    ...
    v = extend(v,n,sum);
    

    另一件不正确的事情是您对新元素的初始化,n 应该包含新元素的数量加上任何旧的,因为您希望分配的块更大。最好给它新旧数量的元素:

    int* extend(int *V, int oldNumber, int newNumber, int s)
    {
        int *pt = realloc(V, newNumber*sizeof(int));
        int i;
        if (pt==NULL) 
        {
          fprintf(stderr,"Out of memory\n");
          return V;
        }
        pt[oldNumber]=s;
        // now you can initialize the rest of the array
        for(i=oldNumber+1;i<newNumber;i++) 
          pt[i] = pt[i-1]*2;
        return pt;
    }
    ...
    v = extend(v,5,n,sum);
    

    【讨论】:

      【解决方案4】:

      像这样增长一个数组

        int capacity = 10; // don't start off as tiny
        ENTRY *array = malloc(capacity * sizeof(ENTRY));
        int N = 0;   //number of entries.
      

      添加

         int addentry(ENTRY *entry)
         {
            ENTRY *temp;
      
            if(N >= capacity)
            {
                temp = realloc(array, (capacity + capacity/2) * sizeof(ENTRY));
                if(!temp)
                  goto out_of_memory;
                array = temp;
                capacity = capacity + capacity/2;
            }
            array[N] = *entry;
            N++;
            return 0;
          out_of_memory:
              //always a problem, maybe terminate program here
              // as it is, just shunt up
              return -1;
         }
      

      你需要 temp 因为 realloc 在失败时返回 0 但保持 参数完好无损,因此您需要保留数组以销毁它 优雅地。增长1.5左右,加倍太激进了 每次调用都重新分配太昂贵了。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2014-05-25
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多