C语言 我们可以访问已释放的内存吗?



我注意到函数的局部变量一直获得相同的内存,所以我尝试在从函数返回后访问内存。(我试图访问已解除分配的内存(

第一次尝试:在第一个代码中,我返回了局部变量的地址(也得到了编译器的警告(,然后当我尝试访问此内存时 主,程序由于分段错误而停止。

#include<stdio.h>
int * fun()
{
int a;
printf("Address of a is %pn",&a);
printf("Value of a is %dn",a);
return &a;
}
int main()
{
int *p;
p=fun();
*p=100;//Segmentation fault: program stops execution at this line 
// which can be verified as the printf statement in next line doesn't execute
printf("Hi");
fun();
}

输出:testC.c:26:12:警告:函数返回局部变量的地址 [-Wreturn-local-addr] 返回和 a; ^~

a 的地址是 000000000061FDDC

a 的值为 0

第二次尝试:现在我尝试了同样的事情,但有点扭曲,我没有直接返回地址,而是在额外指针的帮助下返回了它,在这种情况下,我没有收到编译器的任何警告,我成功地访问了 main 中释放的内存,方法是在该地址放置值 100,可以在下一次函数调用期间看到。

#include<stdio.h>
int * fun()
{
int a,*p;
printf("Address of a is %p nAddress of p is %pn",&a,&p);
printf("Value of a is %dn",a);
p=&a;
return p;
}
int main()
{
int *p;
p=fun();
*p=100;//Segmentation fault: program doesn't stop here
//compiler is not able to catch this fault and we access a deallocated memory
//and successfully insert 100 at a deallocated memory, which we can see in next fun() call.
fun();
}

输出:

a 的地址是 000000000061FDDC

p 的地址是 000000000061FDD0

a 的值为 0

a 的地址是 000000000061FDDC

p 的地址是 000000000061FDD0

a 的值为 100

有人可以解释一下如何访问这样的已释放内存吗?

有时,未定义的行为会像你期望的那样工作 - 毕竟,这是它可以做的无数事情之一,也是它最阴险的功能 - 从程序员的角度来看,如果它每次都崩溃并带有信息性消息会更好(然而,这几乎肯定会减慢 C 的速度,以至于人们会大声疾呼旧行为(。

可能起作用的事实绝不是一个好主意,因为它也可以做其他无数负一的事情之一,例如形成一个微型黑洞,在蒸发之前吞噬你的一半房子,或者在播放文件时擦除你的存储设备derisive_laughter.mp3:-(

详细信息可以在(C11(6.2.4 Storage durations of objects中找到:

对象的生存期是程序执行期间保证为其保留存储的部分。对象存在,具有常量地址,并在其整个生存期内保留其最后存储的值。如果对象在其生存期之外被引用,则行为是未定义的。当指针指向(或刚刚过去(的对象达到其生存期结束时,指针的值将变得不确定。

您的a变量是自动变量,如同一部分所示:

声明标识符时没有链接且没有存储类说明符 static 的对象具有自动存储持续时间

对于没有可变长度数组类型的此类对象,其生存期从进入与其关联的块开始,直到该块的执行以任何方式结束。

由于该a变量的生命周期在fun()结束时停止,指向它的指针变得不确定,这在6.5.3.2 Address and indirection operators中有所介绍:

如果为指针分配了无效值,则一元运算符*的行为是未定义的。

该部分引用了以下脚注:

一元*运算符取消引用指针的无效值包括 null 指针、与指向的对象类型不恰当对齐的地址以及对象生存期结束后的地址。

相关内容

  • 没有找到相关文章

最新更新