C++ 当构造函数引发异常时删除运算符segfaults
最好从代码开始理解这一点C++ 当构造函数引发异常时删除运算符segfaults,c++,class,exception,delete-operator,C++,Class,Exception,Delete Operator,最好从代码开始理解这一点 #include "Hello1.h" #include "Hello2.h" int main(int argc, char ** argv) { // Hello1 and Hello2 are derevied classes of Hello // And there constructor throws an exception Hello * h; try { if (argv[1][0]=='1'
#include "Hello1.h"
#include "Hello2.h"
int main(int argc, char ** argv)
{
// Hello1 and Hello2 are derevied classes of Hello
// And there constructor throws an exception
Hello * h;
try
{
if (argv[1][0]=='1')
h = new Hello1;
else
h = new Hello2;
}
catch (std::exception ex) { /*print error*/ }
delete h;
}
如果Hello1
和Hello2
抛出异常,则它segfault。但是如果我加上
Hello h = NULL;
它可以工作强>
Hello是一个带有构造函数的类,它抛出了一个异常
我所能想到的就是构造函数中的异常将对象从内存中删除!为什么是谁…解释!求你了
但是,如果我添加Hello h=NULL代码>它工作!!!为什么是谁…解释!求你了
这是因为运算符delete
在指针为null
时不执行任何操作。人们期望它什么也不做,这是标准行为。C++11标准第3.7.4.2段规定:
[…]价值
提供给释放函数的第一个参数可以是空指针值;如果是,如果取消分配
函数是标准库中提供的函数,调用无效。[……]
另一方面,如果它不是null
,操作符delete
将尝试删除hello
指向的对象,并且由于指针未初始化(因为在发生对hello
的赋值之前,已抛出构造并将控制转移到异常处理程序),您将获得未定义的行为
根据第5.3.5/2段:
[…]在第一个备选方案(删除对象)中,delete
的操作数的值可能是空指针
值、指向由以前的新表达式创建的非数组对象的指针或指向子对象的指针(1.8)
表示此类对象的基类(第10条)如果不是,则行为未定义。[……]
为什么是谁…解释!求你了
如果Hello
的构造函数抛出的h
从未初始化-delete
尝试从未初始化的变量和未定义的行为中读取
我建议使用智能指针。delete
如果尝试删除不应删除的内容,则会引发异常。正如其他人指出的,delete
如果试图删除设置为null的内容,则不会抛出
new
据我所知,除非内存不足,否则永远不会抛出
所以发生的情况是,argv[1]
不是'1'
,这意味着h指向未知的东西,这使得delete
抛出异常什么是Hello
?Atypedef
用于指针类型或可由自身指针构造的类型?如何h=new Hello1如果h
不是指针,则代码>编译?或者你的意思是说,Hello*h
?@Andy Prowl你是对的,对不起,我是凭记忆写的。什么是异常
?所以你的意思是std::exception
?@angle.King.47:请不要“从内存中写入”,请确保您实际发布的代码编译并生成您发布的实际错误。这让每个人都不必再胡说八道了。所以我认为,如果构造函数中抛出了任何异常,那么这些异常总是会决定类是未定义的。@angle.King.47:我想你说的是正确的,但不准确。对象的生命周期从其初始化完成时开始。对于类类型,这是构造函数返回的时间。由此得出的结论是,如果在构造函数中抛出异常,则对象永远不会开始存在。如果这是您的意思,那么答案是“是”。这很完美,“如果在构造函数中引发异常,则对象从未开始存在。”这正是我所需要的。注意:如果您在引发异常之前在构造函数中分配其他动态内存(通过new),则您有责任在引发异常之前将其清理干净。