分割错误而不是构造函数调用
Segmentation fault instead of constructor call
我正在尝试修改内置分配函数:
#include <iostream>
#include <cstdlib>
#include <new>
struct A
{
int a;
A(){ std::cout << "Constructorn"; a = 3; }
void* operator new(std::size_t t) noexcept
{
::operator new(t);
return NULL;
}
};
int main()
{
new A();
}
演示我用segmentation fault
代替构造函数调用。你能解释一下这种行为吗?
您有一个bug,因为对::operator new()
的调用可能抛出std::bad_alloc
,违反了特定于类的分配器的异常规范(zybox的答案显示了如何修复这个问题)。然而,这在这么小的程序中是不太可能发生的。在不提供operator delete()
的情况下覆盖operator new()
也是一个坏主意,尽管我找不到一个明确的要求,即两者必须在同一范围内找到。
从分配器返回空指针是指示分配失败的合法且正确的方式。在3.7.4.1中,标准规定:
分配函数如果分配存储失败,可以调用当前安装的new-handler函数(18.6.2.3)。[注:程序提供的分配函数可以通过
std::get_new_handler
函数(18.6.2.4)获得当前安装的new_handler
的地址。]如果用非抛出异常规范(15.4)声明的分配函数分配存储失败,它应该返回一个空指针。任何其他分配函数如果分配存储失败,只能抛出与类型std::bad_alloc(18.6.2.1)的处理程序(15.3)匹配的异常(15.1)来表示失败。
在5.3.4中:
如果分配函数返回null,则不进行初始化,不调用分配函数,new-expression的值为null。
代码在::operator new()
不抛出的路径上是合法的——main()
中的表达式new A()
计算为空指针,这是可以的,因为它永远不会被解引用。
也不应该调用构造函数。您应该得到的是内存泄漏,因为在分配器中没有对应于::operator new(t)
的::operator delete()
调用。
您的函数操作符new
包含null
指针,因此实际上不返回任何内容。
null
函数操作符等于return false;
,或者只是return;
,但要注意:如果不小心,使用new
操作符复制指针会导致内存泄漏。为了解决这个问题,当你完成时,只需delete(t)
。
下面的代码将解决您的问题:
#include <iostream>
#include <cstdlib>
#include <new>
struct A
{
int a;
A(){ std::cout << "Constructorn"; a = 3; }
void* operator new(std::size_t t) noexcept
{
return ::operator new(t, std::nothrow);
}
};
int main()
{
new A();
}
原始代码只是从A::operator new
返回NULL
,悄悄地忘记了::operator new
的返回结果(内存泄漏)。崩溃的原因是返回的指针随后被用作新的A
对象的this
指针。由于该指针是NULL
,构造函数对对象所做的任何操作(赋值a = 3
)都是对NULL
的解引用。这导致了分割冲突。Zyboxinternational上面的答案给出了一个很好的解决方案,前面两个海报的评论都非常相关。
- C++模板类 - 继承调用错误的函数
- 使用 std::find 时没有匹配的函数调用错误
- C++命名空间中调用 void 函数的错误
- 使用成员初始值设定项列表时没有匹配的函数调用错误
- C ++尝试访问映射中的元素会给我一个不匹配的函数调用错误
- C++类静态成员函数调用错误
- 如何调查随机安卓原生函数调用错误?
- C++:函数调用错误:标识符"name"未定义,如果已定义?
- 复制构造函数调用错误
- 当我使用由unsigned int和unsigned long区分的重载函数时,引发了不明确的函数调用错误?这种重载有效
- 没有匹配的函数调用错误
- 虚函数调用错误的函数,在C++和Cocos2dX中的名称完全不同
- 纯虚拟函数调用错误
- 我的类出现函数调用错误
- 内联函数调用错误
- 函数调用错误
- 模板构造函数没有匹配函数调用错误
- 模板化成员函数调用g++错误:没有匹配的函数用于调用
- 模板函数调用错误503
- 擦除函数调用错误