0

考虑以下代码(使用 g++ 构建):

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

typedef struct {
    int a;
    int b;
    char c;
} memstr_t;

memstr_t *ptt_backup;

void mmm(memstr_t*& ptt)
{
    ptt = (memstr_t *)calloc(15, sizeof(memstr_t));
    ptt[0].a = 1;
    ptt[0].b = 2;
    ptt[0].c = 'c';
    ptt_backup = ptt;
}

void fff()
{
    free(ptt_backup);
}

int main(int argc, char *argv[])
{
    memstr_t *ptt;

    mmm(ptt);
    printf("%d %d %c\n", ptt[0].a, ptt[0].b, ptt[0].c);
    getchar();
    //fff();
    free(ptt); // same as fff()?
    printf("%d %d %c\n", ptt[0].a, ptt[0].b, ptt[0].c); //why works?
    getchar();
    return 0;
}

我不明白:

1)为什么我释放内存后第二次打印没有段错误?我仍然得到我分配的值mmm()

2)free()fff()做同样的事情吗?

4

5 回答 5

2

1)取消引用释放的内存可以做任何事情。它可能存在,也可能不存在,这是未定义的行为,可以做任何事情,包括给你的猫发传真。

2) 是的,free() 和 fff() 做同样的事情,因为它们都指向同一个内存位置。

于 2013-06-14T13:01:14.063 回答
1

第二次打印使用不再有效的指针,这使得行为未定义。无论可能发生什么,包括是什么让你相信它“有效”,以及其他任何时候它都可能完全是另外一回事。不要那样做!

2:在这个代码片段中它们具有相同的效果。

于 2013-06-14T13:02:22.260 回答
0

calloc分配内存并返回一个指向已分配内存的指针。

mmm你分配pttptt_backup. 现在他们都指向同一个地方。(仅仅因为我有一个名字和一个昵称,这并不能复制我的两个副本。我是一个可以通过两个不同名字访问的人)

In fffyou are freeing ptt_backup(读为freeing 指向的内存ptt_backup)也是 指向的内存。ptt这意味着您现在无法使用该内存。它仍然可以保留值,但未定义依赖它。看到这个很好的答案, 可以在其范围之外访问局部变量的内存吗?

printf("%d %d %c\n", ptt[0].a, ptt[0].b, ptt[0].c);可能并不总是有效。

然后,当您执行已被 删除的free(ptt)(将其读取为free指向的内存)时,如所述,它是未定义的行为,pttfff

free() 函数将导致 ptr 指向的空间被释放;也就是说,可供进一步分配。如果 ptr 是空指针,则不会发生任何动作。否则,如果参数与 calloc()、malloc()、[ADV] posix_memalign()、realloc() 或 [XSI] strdup() 函数先前返回的指针不匹配,或者如果空间已被释放调用 free() 或 realloc(),行为未定义。

于 2013-06-14T13:10:02.163 回答
0
  1. Using a memory pointer that points to freed memory leads to undefined behavior. This means that a segfault doesn't necessarily happen, but is possible. Therefore, you never should dereference freed memory.

  2. They (fff and free) are the same thing in this context, because they point to the same address.

于 2013-06-14T13:21:40.053 回答
-1

您永远不会为ptt_backup! 您处于未定义的行为领域;任何事情都可能发生在fff()

于 2013-06-14T12:59:33.043 回答