当构造函数抛出异常时,删除运算符段错误

时间:2013-05-02 09:10:30

标签: 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')
            h = new Hello1;
        else
            h = new Hello2;
    }
    catch (std::exception ex) { /*print error*/ }

    delete h;
}

如果Hello1Hello2引发异常,则 segfault 。但是,如果我添加

Hello h = NULL;

有效!!!

Hello是一个带有构造函数的类,它抛出异常

所有我能想到的是构造函数中的异常从内存中删除对象!为什么谁...谁解释!请。

3 个答案:

答案 0 :(得分:6)

  

但是,如果我添加Hello h = NULL;,它就可以了!为什么谁...谁解释!请。

这是因为operator delete在指针为null时什么都不做。预计什么都不做,这是标准行为。 C ++ 11标准的第3.7.4.2段规定:

  

[...]的价值   提供给释放函数的第一个参数可以是空指针值;如果是的话,如果解除分配   功能是标准库中提供的功能,呼叫无效。 [...]

如果它不是null,另一方面,operator delete将尝试删除hello指向的对象,并且因为指针未初始化(因为构造投掷并控制在分配给hello之前转移到异常处理程序中,您得到未定义的行为

根据第5.3.5 / 2段:

  

[...]在第一个备选方案(删除对象)中,delete的操作数的值可能是空指针   value,指向前一个new-expression创建的非数组对象的指针,或指向子对象的指针(1.8)   表示这种对象的基类(第10条)。 如果不是,则行为未定义。 [...]

答案 1 :(得分:1)

  

为什么谁......解释!请。

如果Hello的构造函数抛出h从未初始化 - delete尝试从未定义的未初始化变量和行为中读取。

我建议使用智能指针。

答案 2 :(得分:0)

如果您尝试删除不应删除的内容,

delete会抛出异常。正如其他人所指出的,如果您尝试删除设置为delete

的内容,null将不会抛出 据我所知,

new除非你失去记忆,否则永远不会抛出。

所以会发生argv[1]不是'1',这意味着h指向未知的东西,这会使delete抛出异常