考虑以下代码(使用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()
做同样的事情吗?
答案 0 :(得分:2)
1)解除引用free'd内存可以做任何事情。它可能存在,它可能不存在,它是未定义的行为,可以做任何事情,包括传真你的猫。
2)是的,free()和fff()做同样的事情,因为它们都指向相同的内存位置。
答案 1 :(得分:1)
第二次打印使用不再有效的指针,这使得行为未定义。无论发生什么,包括让你相信它“有效”的东西,以及任何其他时间它都可能是完全不同的东西。不要那样做!
2:在这段代码中,它们具有相同的效果。
答案 2 :(得分:0)
calloc
分配内存并返回指向已分配内存的指针。
在mmm
ptt
中,您将ptt_backup
分配给fff
。现在他们俩都指向同一个地方。 (仅仅因为我有一个名字和一个昵称,不能制作两份我的副本。我是一个可以通过两个不同名字访问的人)
在free
ptt_backup
free
ptt_backup
(读为ptt
printf("%d %d %c\n", ptt[0].a, ptt[0].b, ptt[0].c);
指向的内存,这也是free(ptt)
指向的内容{ {1}}。这意味着您现在无法使用内存。它仍然可以保留值,但它的未定义依赖于它。看到这个好听的答案,
Can a local variable's memory be accessed outside its scope?
free
可能并不总是有效。
然后当你ptt
fff
({{1}}已经被{{1}}删除时{{1}}读取{{1}}时,{{1}}如上所述,
free()函数将导致ptr指向的空间 释放;也就是说,可供进一步分配。如果是ptr 空指针,不会发生任何动作。否则,如果参数确实如此 不匹配calloc(),malloc(),[ADV]返回的指针 posix_memalign(),realloc()或[XSI] strdup()函数,或if 通过调用free()或realloc()来释放空间 行为未定义。
答案 3 :(得分:0)
使用指向释放内存的内存指针会导致未定义的行为。这意味着段错误不会必然发生,但是可能。因此,你永远不应该取消引用释放的内存。
他们(fff和free)在这种情况下是相同的,因为它们指向相同的地址。
答案 4 :(得分:-1)
你永远不会为ptt_backup
分配内存!您处于未定义的行为土地;任何事情都可能发生在fff()