混淆内存损坏c++

confusion on memory corruption c++

本文关键字:c++ 损坏 内存      更新时间:2023-10-16
class Test {
    int a ;
    int b ;
    public :
    Test() { }
    Test(int x , int y) : a(x),b(y) { }
    int getA() { return a ;}
    int getB() { return b ;}
};
int main () {
    list <Test *> mylist;
    Test *t1 = new Test(10,20);
    mylist.push_back(t1);
    delete t1 ;   //deleting the pointer
    list <Test*> ::iterator it ;
    for( it = mylist.begin() ; it != mylist.end() ; ++it ) {
        Test *temp = (*it) ;
        cout<<"taking data from list="<<temp->getB()<<endl;
    }
    return 0 ;
}

我对程序的输出感到困惑,在列表中插入指针后,我删除了指针。理想情况下,它应该给出分段错误,但它正在打印0。

delete t1 ;   //deleting the pointer

这个delete不是指针,而是这个指针指向的对象。

当您在std::listpush_back指针时,只复制指针,而不复制实际对象。

处理这一问题的两种标准方法是:

  • 如果真的需要在容器中存储指针,那么delete就是对象,当你知道list将不再使用时
  • 避免这种问题的最常见的方法是具有CCD_ 6而不是CCD_

进行时

delete t1 ;   //deleting the pointer

您删除的是指针指向的对象,而不是指针本身(按值复制到列表中(。

稍后获取指针是完全有效的操作

Test *temp = (*it) ;

无效的是使用指向已删除内存的指针,这将导致未定义的行为

cout<<"taking data from list="<<temp->getB()<<endl;

这意味着您可能会获得访问冲突或垃圾值,甚至是旧值,具体取决于内存的管理方式。

调用delete t1,只需调用对象的析构函数并释放内存。指针的值不变。它只是内存地址的值。

因此,您仍然可以访问t1所指向的内存块。但这种行为是不明确的。

通过调试,您可能会得到无效数据。因为一些调试堆实现使用字节模式填充释放的内存。在一个发布程序中,您可能会得到旧值和程序接缝以正确工作。