异常对象类型 生命期
#include <iostream>
using namespace std;
class Err
{
private:
int a;
int b;
public:
Err(int m,int n):a(m),b(n)
{
}
void msg()
{
cout < < "a == -b is error " < <endl;
}
~Err()
{
cout < < "here ,it will be destoryed! " < <endl;
}
};
int test(int a,int b);
void main()
{
try
{
int gg = test(4,-4);
}
catch (Err* e)
{
e-> msg();
}
}
int test(int a,int b)
{
if (a == -b)
{
Err d(a,b);
throw &d;
}
else
return a+b;
}
跟踪程序:throw &d 后就立刻调用~Err().请问catch (Err* e)中的e为什么还能调用msg方法。
[解决办法]
~Err()
{
a = 0x55;
b = 0xAA;
cout < < "here ,it will be destoryed! " < <endl;
}
你再看看你捕获的时候,a/b还是你原来想要的值吗。
对象被析构了,地址值还在,地址里面的内容还未必被破坏。
访问失效内存区,后果未可知。C和C++的基本常识了。
[解决办法]
throw by value, catch by reference.
[解决办法]
大多数情况下,执行动态内存分配的的类都在构造函数里用new分配内存,然后在析构函数里用delete释放内存。最初写这个类的时候当然不难做,你会记得最后对在所有构造函数里分配了内存的所有成员使用delete。
然而,这个类经过维护、升级后,情况就会变得困难了,因为对类的代码进行修改的程序员不一定就是最早写这个类的人。而增加一个指针成员意味着几乎都要进行下面的工作:
在每个构造函数里对指针进行初始化。对于一些构造函数,如果没有内存要分配给指针的话,指针要被初始化为0(即空指针)。
删除现有的内存,通过赋值操作符分配给指针新的内存。
在析构函数里删除指针。
[解决办法]
呵呵,楼上分析都正确。
补充一句,这种表面上的正确结果实际上隐藏着危机,如果恰好这时候有人把你的那块内存用掉了,你就挂定了。
:)
[解决办法]
参考:http://www.ieee.org.cn/dispbbs.asp?boardID=61&ID=34997
[解决办法]
http://blog.csdn.net/foxbillcsdn/archive/2006/05/24/752281.aspx
[解决办法]
程序进入了catch函数,当然要执行msg方法了,你单步跟踪下哪里是你不想看到的结果,再看下能否分析出出错的原因。
[解决办法]
楼主已经知道了throw &d 后就立刻调用~Err().说明d被析构了。
所以这个问题应该不是关于异常传递的问题,而是作用域的问题了。
其实楼主这个类这样调用msg()函数是安全的,关键在于msg()函数内部没有访问类的数据成员。
看下面:
Err *e=0;
e-> msg(); //OK,不会有问题
这是因为成员函数的调用其实和普通函数差不多,编译器只不过自动多加了一个this指针的参数而已,但是如果函数内部没有利用这个this指针存取成员变量,我们上面的例子就是安全的,毕竟多了一个没有用的参数对函数来说无所谓。
[解决办法]
但是如果msg()函数内部访问了数据成员,结果就会像前面各位分析的那样,存在潜在危险。
而这时我们的这个例子肯定是要挂调的
Err *e=0;
e-> msg(); //如果msg有访问数据成员,但是指针e根本就是一个空指针,不死才怪
[解决办法]
mark