C 具有不同指针的相同地址


int *ptr = calloc(10,(sizeof(int)));
int *ptr2 = (ptr);
for (int i = 0; i < 10; ++i) {
    int r = rand() % 20000;
    *(ptr + i) = r;
    printf("[i:%d, v:%d, a:%p]", i, *(ptr + i), ptr+i);
    fflush(stdout);
}
printf("n");
printf("[v:%d, a:%p]", *(ptr2), ptr2);
printf("n");
*ptr2=5;
printf("[v:%d, a:%p]", *(ptr2), ptr2);
printf("n");
for (int i = 0; i < 10; ++i) {
    printf("[i:%d, v:%d, a:%p]", i, *(ptr + i), ptr+i);
}
printf("n");
free(ptr2);
free(ptr);

这是输出:

[i:0, v:5933, a:0x600010360][i:1, ...
[v:5933, a:0x600010360]
[v:5, a:0x600010360]
[i:0, v:5, a:0x600010360][i:1, ...

请解释为什么同一地址有两个不同的值? - 这实际上不会发生。

而且以我的方式释放指针也会给出错误:

*

glibc 检测到 */home/travis/build/batousik/Practical C2/bin/.libs/lt-practical_trees:双重释放或损坏(快速顶部):0x0000000000e05010 ***

在实际程序中,我在 int 数组和 Tree 数据类型中具有测试数据。我用数组中的一些数据填充 Tree,然后我尝试递归释放树中节点和节点的每个值,但失败了。是因为节点中的所有值指针实际上都是一个内存块吗?然后我是否应该做一些类似将数组中的值复制到节点值新分配的内存空间之类的操作?

  1. 因为您要释放同一指针两次。您指向以下行中由 calloc() 1 返回的地址

    ptr = calloc(10, sizeof(int));
    

    然后你ptr2指向同一个地方

    ptr2 = ptr;
    

    因此,释放ptrptr2实际上免费的是相同的指针。

  2. 没有任何迹象表明给定地址的值实际上有两个值,只是

    *ptr2 = 5;
    

    更改 ptrptr2 指向的第一个元素的值,实际上您总是在打印之前覆盖该地址的值。

如果在代码中出现有问题的free()调用之前执行此操作

fprintf(stderr, "value of ptr : %pn", ptr);
fprintf(stderr, "value of ptr2: %pn", ptr2);

将打印相同的值,因此您实际上需要一次调用来free()传递任何ptrptr2,但在传递后不需要传递另一个。


1如果要在calloc()调用后立即显式初始化数据,则无需使用 calloc()。而且,您应该检查calloc()/malloc()是否没有返回NULL

int *ptr2 = (ptr);

这只是复制指针的值。在此行之后,ptrptr2 都指向相同的分配内存。然后

free(ptr2);
free(ptr);

您将释放两次相同的分配。

我不太确定你的代码应该做什么。您有两个循环,它们都覆盖相同的内存块。出于某种原因,您还将 5 写入该块中的第一个int

同一地址中的两个值是因为这个

*ptr2 = 5

glibc 错误是因为双free(ptr)free(ptr2)

最新更新