0

最好从代码开始了解这一点

#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;
}

如果Hello1andHello2抛出异常, It segfault。但是,如果我添加

Hello h = NULL;

有用!!!

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

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

4

3 回答 3

6

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

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

[...] 提供给释放函数的第一个参数的值可能是空指针值;如果是这样,并且如果释放函数是标准库中提供的函数,则调用无效。[...]

null另一方面,如果不是,operator delete则将尝试删除 指向的对象hello,并且由于指针未初始化(因为在分配发生之前已抛出构造,并且控制已转移到异常处理程序hello),您会得到未定义的行为

根据第 5.3.5/2 段:

[...] 在第一种选择(删除对象)中,操作数的值delete可以是空指针值、指向由先前的 new 表达式创建的非数组对象的指针或指向子对象的指针( 1.8) 表示此类对象的基类(第 10 条)。如果不是,则行为未定义。[...]

于 2013-05-02T09:13:17.853 回答
1

为什么在哪里谁...解释!请。

IfHello的构造函数 throwsh从未初始化 -delete尝试从未初始化的变量和未定义的行为中读取。

我建议使用智能指针。

于 2013-05-02T09:13:29.847 回答
0

delete如果您尝试删除不应删除的内容,可能会引发异常。正如其他人指出的那样,delete如果您尝试删除设置为的内容,则不会抛出null

new据我所知,除非你没有记忆,否则永远不会扔。

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

于 2013-05-02T09:22:59.290 回答