我尝试对内置分配功能进行一点修改:
#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();
}
而不是构造函数调用我得到了segmentation fault
。你能解释一下这种行为吗?
答案 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上面给出的答案提供了一个很好的解决方案,之前两张海报的评论非常相关。