分段错误而不是构造函数调用

时间:2014-07-20 19:12:42

标签: c++ constructor

我尝试对内置分配功能进行一点修改:

#include <iostream>
#include <cstdlib>
#include <new>

struct A
{
    int a;
    A(){ std::cout << "Constructor\n"; a = 3; }
    void* operator new(std::size_t t) noexcept
    {
        ::operator new(t);
        return NULL;
    }
};

int main()
{
    new A();
}

demo

而不是构造函数调用我得到了segmentation fault。你能解释一下这种行为吗?

3 个答案:

答案 0 :(得分:5)

你有一个错误,因为对::operator new()的调用可能会抛出std::bad_alloc,违反了特定于类的分配器的异常规范(zybox的answer显示了如何解决此问题)。但是,这种小程序不太可能发生。在不提供operator new()的情况下覆盖operator delete()也是一个坏主意,尽管我找不到明确要求必须在同一范围内找到它们。

从分配器返回空指针既合法又是指示分配失败的正确方法。在3.7.4.1中,标准说:

  

无法分配存储的分配函数可以调用当前安装的新处理函数(18.6.2.3)(如果有)。 [注意:程序提供的分配函数可以使用new_handler函数(18.6.2.4)获取当前安装的std::get_new_handler的地址。 - 结束注释]如果使用非抛出异常 - 规范(15.4)声明的分配函数无法分配存储,则它应返回空指针。任何其他无法分配存储的分配函数都应仅通过抛出与std :: bad_alloc(18.6.2.1)类型的处理程序(15.3)匹配的类型的异常(15.1)来指示失败。

然后在5.3.4:

  

如果分配函数返回null,则不进行初始化,不应调用释放函数,并且new-expression的值应为null。

代码在::operator new()不抛出的路径上是合法的 - new A()中的表达式main()计算为空指针,这是好的,因为它永远不会被解除引用。

您也不应该进行构造函数调用。你应该得到的是内存泄漏,因为没有::operator delete()调用对应于你的分配器内的::operator new(t)

答案 1 :(得分:1)

您的函数运算符new包含null指针,因此实际上并没有返回任何内容。

null函数运算符等于return false;return;,但要注意:如果你不是&#,那么使用new运算符复制指针会导致内存泄漏39;小心。要解决这个问题,只需delete(t)即可完成。

以下代码将解决您的问题:

#include <iostream>
#include <cstdlib>
#include <new>

struct A
{
    int a;
    A(){ std::cout << "Constructor\n"; a = 3; }
    void* operator new(std::size_t t) noexcept
    {
        return ::operator new(t, std::nothrow);
    }
};

int main()
{
    new A();
}

答案 2 :(得分:0)

原始代码只是从NULL返回A::operator new,悄然忘记::operator new的返回结果(内存泄漏)。崩溃的原因是返回的指针随后被用作新this对象的A指针。由于该指针为NULL,因此构造函数对该对象执行的任何操作(分配a = 3)都将取消引用NULL。这会导致细分违规。 zyboxinternational上面给出的答案提供了一个很好的解决方案,之前两张海报的评论非常相关。