1

使用我在这里学到的知识:How to use realloc in a function in C,我编写了这个程序。

int data_length; // Keeps track of length of the dynamic array.
int n; // Keeps track of the number of elements in dynamic array.

void add(int x, int data[], int** test)
{

    n++;

    if (n > data_length)
    {
        data_length++;
        *test = realloc(*test, data_length * sizeof (int));
    }

    data[n-1] = x;

}

int main(void)
{

    int *data = malloc(2 * sizeof *data);

    data_length = 2; // Set the initial values.
    n = 0;

    add(0,data,&data);
    add(1,data,&data);
    add(2,data,&data);

    return 0;
}

该程序的目标是拥有一个动态数组data,我可以不断向其中添加值。当我尝试向 中添加一个值时data,如果它已满,则使用 realloc 增加数组的长度。

问题

该程序可以编译,运行时不会崩溃。但是,打印出data[0], data[1],data[2]给出0,1,0. 该号码2未添加到数组中。

这是因为我使用错误realloc吗?

附加信息

该程序稍后将与不同数量的“添加”和可能的“删除”功能一起使用。另外,我知道realloc应该检查它是否失败 (is NULL),但为了简单起见,这里省略了。

我仍在学习和尝试 C。感谢您的耐心等待。

4

3 回答 3

2

您的问题在于您对 的使用 data,因为它指向旧数组的地址。然后,当您拨打电话时realloc,该区域将被释放。因此,您正试图在下一条指令上访问无效地址:这会导致未定义的行为。

你也不需要使用这个data指针。test足够了。

(*test)[n-1] = x;
于 2012-12-06T18:12:00.600 回答
1

你不需要传递data两次到add.

你可以编码

void add(int x, int** ptr)
{
  n++;
  int *data = *ptr;
  if (n > data_length) {
    data_length++;
    *ptr = data = realloc(oldata, data_length * sizeof (int));
    if (!data) 
      perror("realloc failed), exit(EXIT_FAILURE);
  }
  data [n-1] = x;
}

但这非常低效,您应该realloc偶尔调用一次。例如,您可以

     data_length = 3*data_length/2 + 5;
     *ptr = data = realloc(oldata, data_length * sizeof (int));
于 2012-12-06T18:11:44.527 回答
1

让我们看一下POSIX realloc 规范

描述说:

如果内存对象的新大小需要移动对象,则释放对象先前实例化的空间。

返回值(强调添加)提到:

在大小不等于 0 的情况下成功完成后,realloc() 返回一个指向(可能已移动)分配空间的指针。

您可以检查指针是否发生变化。

int *old;
old = *test;
*test = realloc(*test, data_length * sizeof(int));
if (*test != old)
    printf("Pointer changed from %p to %p\n", old, *test);

这种可能的更改可能会产生不良影响,因为您的代码通过两个不同的名称引用“相同”内存,data并且*test. 如果*test发生变化,data仍然指向旧的内存块。

于 2012-12-06T18:24:07.200 回答