【问题标题】:Realloc error in CC中的Realloc错误
【发布时间】:2012-08-12 01:37:55
【问题描述】:

我刚刚开始 C 阅读手册页,但找不到正确的答案。所以代码如下

void *p = malloc(10*sizeof(int));
int *q = p;
int NUMOFINT = 10;
for (int i = 0; i < NUMOFINT; i++){
printf("%i ", q[i]);
}
void *realloc(void *p, 20*sizeof(int));
for (int i = 0; i < 21; i++){
printf("%i ", q[i]);

它给出了这个错误:

malloc.c: In function ‘main’:
malloc.c:31:24: error: expected declaration specifiers or ‘...’ before numeric constant

我不太明白 malloc() 的大小格式可以,但 realloc 的大小格式不行。那么如何纠正错误呢?

编辑:

所以当我把它变成:

void *morep = realloc(p, 20*sizeof(int));
int *q2 = morep;
for (int i = 0; i < 20; i++){
printf("%i ", q2[i]);
}

它将q2[11] 打印为135121

【问题讨论】:

  • 对 realloc 的调用一团糟,可能是 void *new_p = realloc(p, 20*sizeof(int)); 之类的东西。您尚未声明一个指针来保存 realloc 的返回值,并且在调用该函数时您正在(重新)声明一个指针 p
  • 那会重新分配实际的 p void 吗?
  • 是的,如果您在 *nix 系统上,请参阅功能 documentationman 页面了解更多详情
  • 另外,第二个 for 循环应该是 20,而不是 21。当它的大小为 20 时,您不想读取 p[20]。
  • 您的realloc 行看起来像是原型和调用的混合体。您不需要原型(它在标题 &lt;stdlib.h&gt; 中),调用应该类似于 tmp = realloc(oldpointer, &lt;NEW_SIZE&gt;); if (!tmp) /* error */; oldpointer = tmp;

标签: c pointers malloc void realloc


【解决方案1】:

realloc 可以尝试扩展堆中现有的内存块,如果不可能,它将为新大小分配一个新的单独内存块,并将数据从旧内存块复制到新内存块.

所以如果 realloc 返回与p 相同的地址,那么它只会扩展旧的内存块。否则我们必须释放旧内存块并开始使用realloc 返回的新内存块。

#define NUMOFINT 10
#define NUMOFINT_NEW 20

void *p = malloc(NUMOFINT * sizeof(int)); 
int *q = p; 
void *temp = NULL;

for (int i = 0; i < NUMOFINT; i++)
{ 
    printf("%i ", q[i]); 
} 

temp = realloc(p, NUMOFINT_NEW * sizeof(int)); 
if (temp == NULL)
{
    exit(0);
}
else if (temp != p)
{
    free(p);
    p = temp;
}

//else temp is equal to p

for (int i = 0; i < NUMOFINT_NEW; i++)
{ 
    printf("%i ", q[i]); 
}

这里q[0]q[9] 将具有分配的值(0, 1, 2..9),其余的(q[10]q[19])将具有垃圾值。我们还没有memset新分配的内存给0

你也可以在for loop之前进行memset,

memset((q + NUMOFINT), 0, (NUMOFINT_NEW - NUMOFINT));

你的程序中的错误是

1) 编译错误,因为 void *realloc(void *p, 20*sizeof(int)); 这个语句看起来不像函数调用。

2) for (int i = 0; i &lt; 21; i++) - 内存重新分配给 20 元素后,您最多只能访问 19th,访问 20th 可能会导致崩溃(未定义行为)。

3) it prints out q2[11] as 135121 - 新分配的内存既不是 memset0 也不是分配任何有意义的值。

【讨论】:

    【解决方案2】:
    #include <stdlib.h>
    #include <string.h>
    #include <errno.h>
    #include <stdio.h>
    
    int main(int argc, char **argv)
    {
            int *temp;  /* To use with realloc, it's more secure */
            void *p = malloc(10*sizeof(int));
            int *q = p;
            int NUMOFINT = 10;
    
            /* dont forget to compile with -std=99 flag, if you use this kind of for loop */
            for (int i = 0; i < NUMOFINT; i++){
                    printf("%i ", q[i]);
            }
            printf("\n");
    
            /* It's more secure to use this kind of realloc */
            temp = realloc (p, 20 * sizeof(int) );
            if (temp == NULL)
            {
                    fprintf(stderr,"Reallocation failed --> %s\n", strerror(errno));
                    free(p);
    
                    exit(EXIT_FAILURE);
            }
            else
            {
                    p = temp;
            }
    
            /* Zeroing after realloc */
            for (int i = NUMOFINT; i < 21; i++)
                    q[i] = 0;
    
            for (int i = 0; i < 21; i++)
            {
                    printf("%i ", q[i]);
            }
            printf("\n");
    
            return 0;
    }
    

    【讨论】:

      【解决方案3】:

      这个

      void *realloc(void *p, 20*sizeof(int));
      

      错了。你想要的

      p = realloc(p, 20*sizeof(int));
      

      顺便说一句,这一行也是一个问题(但会编译得很好):

      for (int i = 0; i < 21; i++){
      

      您为 p 分配了 20*sizeof(int) 个字节,因此元素 20 超出了数组的末尾。你想要:

      for (int i = 0; i < 20; i++){
      

      【讨论】:

      • realloc 的结果分配给同一个旧指针是个坏主意,因为如果重新分配失败,0 将被分配给p,您将失去指向旧内存,反过来又会泄漏。
      • 这种方式仍然将 q2[11] 打印为 135121,而不是 0
      • q2[11] 可以是任何东西。 morep 指向未初始化的内存。你没有给它分配任何东西。试试memset (q2, 0, 20*sizeof(int)),或者做一个for循环,给q2的每个元素赋值。
      • 但是您的代码也发生了同样的情况。我想要的是,当我重新分配数组时,新部分应该全为 0,而不是之前存储在该内存中的任何内容......
      • @SarpKaya:C lib 标准不同意你的观点。您有责任设置新分配的内存块以满足您的需求...
      猜你喜欢
      • 2014-09-22
      • 2015-07-13
      • 2016-10-10
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多