为什么free(arr)仅删除数组的前两个元素?

时间:2018-11-15 12:46:47

标签: c malloc realloc

我有一个简单的代码:

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

int main(void)
{
    int elms = 5;
    int* a = (int*) calloc(elms, sizeof(int));

    *a = elms;
    for(int i = 1; i < elms; i++){
        *(a + i) = i;
    }

    for(int i = 0; i < elms; i++){
        printf("%d ", *(a + i));
    }

    printf("\n");

    free(a);
    // create new array with size increased by one
    int* arr = (int*) realloc(a, (elms + 1) * sizeof(int));
    *(arr + elms) = 10;

    for(int i = 0; i < elms + 1; i++){
        printf("%d ", *(arr + i));
    }

    printf("\n");    

    return 0;
}

run on rextester

在这里,我得到的输出为:

5 1 2 3 4 
0 0 2 3 4 10 

我的问题是,为什么对free()的调用仅删除数组的前两个元素?它应该只删除第一个元素,还是删除所有元素,但是为什么要删除两个元素?

如果我对对free()的呼叫发表评论,则会得到预期的输出:

5 1 2 3 4 
5 1 2 3 4 10 

注意:如果我按预期将realloc的值重新分配回a,则输出不会改变。

3 个答案:

答案 0 :(得分:3)

您可以通过以下方式调用未定义的行为:

free(a);
// create new array with size increased by one
int* arr = (int*) realloc(a, (elms + 1) * sizeof(int));

7.22.3.5 The realloc function, paragraph 3 of the C Standard(在我的脑海中):

  

如果ptr与内存管理函数先前返回的指针不匹配,,或者如果通过调用free realloc函数释放了空间,行为是不确定的。

答案 1 :(得分:2)

您的代码具有未定义的行为。具体来说:

free(a);
... realloc(a, ...);

free(a)之后,a的值不确定。尝试执行任何操作(例如将其传递给函数)具有不确定的行为。

任何结果都是允许的。

答案 2 :(得分:1)

除了其他答案:

您可能想要这样:

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

int main(void)
{
  int elms = 5;
  int* a = (int*)calloc(elms, sizeof(int));

  *a = elms;
  for (int i = 1; i < elms; i++) {
    *(a + i) = i;
  }

  for (int i = 0; i < elms; i++) {
    printf("%d ", *(a + i));
  }

  printf("\n");

  // << don't call free(a) here, once you've done that
  //    a is "gone" forever.

  // create new array with size increased by one
  // << we use the same variable a as before, using another
  //    variable arr as you did is useless and confusing
  a = (int*)realloc(a, (elms + 1) * sizeof(int));
  *(a + elms) = 10;

  for (int i = 0; i < elms + 1; i++) {
    printf("%d ", *(a + i));
  }

  free(a);  // << call free(a) here once you're done with a

  printf("\n");    
  return 0;
}

看看以<<开头的评论

输出:

5 1 2 3 4
5 1 2 3 4 10