关于悬垂指针问题

来源:百度知道 编辑:UC知道 时间:2024/05/08 18:01:30
以下为C++ Primer中简化摘取的一段关于含有指针型数据成员类的代码,按照书中所说应会出现运行错误,但在我的VC++ 6.0+SP6环境下能够正常执行,请各位知情者赐教原委,并说明所用编译环境,谢谢!

#include<iostream>
using namespace std;

class HasPtr{
public:
HasPtr(int *p):ptr(p){}
int *get_ptr() const {return ptr;}
int get_ptr_val() const {return *ptr;}
void set_ptr_val(int val) const {*ptr=val;}
private:
int *ptr;
};

int main(){
int *ip=new int(11); //创建动态int指针ip,指向11
HasPtr obj(ip); //以ip初始化对象obj的指针型数据成员ptr,ptr与ip同时指向11
delete ip; //释放ip
obj.set_ptr_val(22); /*调用set_ptr_val给*ptr赋值33,书上注释为:disaster: the object to which HasPtr points was freed!
并指出"这里的问题是ip和obj中的指针批向同一对象,删除了该对象时,obj中的指针不再指向有效对象。然而
没有办法得知对象已经不存在了。"也就是说此处应出现运行错误,但没有,为什么?*/
cout<<"obj:"<<endl
<<obj.get_ptr()<<endl
<<obj.get_ptr_val()<<endl;
return 0;
}
以下这段代码为什么又不能执行d

用 gcc 编译之后 效果基本一样,编译不报错,运行时也不报错。
不过发现:delete 后面可以跟非空的指针,基本上没有什么自动防范,以至于在上面的问题中:发生了“访问非法内存”、“内存泄露”
不过,在 C++ 里,可以捕获自定义 异常,比较灵活,对于第一个问题,
由于 delete 一个对象之后,可以对那个对象所在的区域“清空”,
ptr指向的内容就成为 0 了,可以根据这个特点做个异常处理:
#include<stdexcept>
void set_ptr_val(int val) const {
  //cout<<(typeid(*ptr).name())<<endl;
  if(!(*ptr)) throw std::runtime_error("0 not allowed");
    *ptr=val;
} // 不能改变成员的值
然后,在主函数里,
try {
  obj.set_ptr_val(22);
} catch (const std::runtime_error& err) {
cout << err.what();
}
就能捕获异常。但是这要求在定义对象的时候,至少初始化为非 0 值,而且在delete 对象之前,都不能随便把对象至 0。

C++的内存泄漏问题,可以到 baidu 搜索更多解决方法。