一个全局指针变量指向栈上的对象的问题

全局指针变量指向栈上的对象的问题

先上代码

#include <iostream>
using namespace std;

class Test
{
public:
    explicit Test(int i):a(i){cout<<"Construct "<<endl;}
    Test(const Test&){cout<<"copy construct"<<endl;}
    ~Test(){cout<<"Destruct"<<endl;}
    int a;
};
Test* testp = NULL;

int main()
{
    {
        Test t(1);
        testp = &t;
    }
    cout<<"t has destructed"<<endl;

    cout<<"testp->a is "<<testp->a<<endl;
    testp->a = 2;

    cout<<"over"<<endl;
    return 0;   
}

运行结果

Construct 
Destruct
t has destructed
testp->a is 1
over

这里就看出了一点问题,testp是一个全局指针,而t只是一个栈上的对象,testp指向了这个对象,但是栈上的对象在生存周期结束后执行了析构操作,但通过全局指针仍然能对这段地址进行访问进行访问,并且,在整个程序结束后也不会再次执行析构操作,那么到底t这个栈上对象析构后真的释放了这段内存吗?为什么数据还是可以访问并且没有变化呢?

下面是我咨询过陈硕大大后给出的解释:
根据 C++ 标准,这是 undefined behavior。When the end of the duration of a region of storage is reached, the values of all pointers representing the address of any part of that region of storage become invalid pointer values. Indirection through an invalid pointer value and passing an invalid pointer value to a deallocation function have undefined behavior.

你可以试试把 Test::a 换成 string 或 vector 类型,看看会发生什么。也可以用 clang 的 AddressSanitizer (Clang 7 documentation) 帮你找错: clang++6.0fsanitize=addressub.cc c l a n g + + − 6.0 − f s a n i t i z e = a d d r e s s u b . c c ./a.out
ERROR: AddressSanitizer: stack-use-after-scope

还有一个网友哆啦安梦给出的解释我也觉得很好:
如果从汇编的角度来看,右大括号结束后会把t这个对象弹出栈,所谓的弹出栈对应的就是一个pop指令,而所谓的pop指令等价于“将栈顶指针向栈底移动sizeof(t)的大小”,原来的t的内容其实还在内存中,只要你不往栈里push新的内容,那这个地址的内容就不会变

Milo Yip老师给出的通俗解释:
你把房间归还给业主,但持着之前备份钥匙还是可进去拾放物品的,不过这是非法的,里面的东西也可能已经被取走,纯粹看运气。遵守合约,维护社会稳定。

我提出的这个问题的知乎链接https://www.zhihu.com/question/266349340

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值