调用派生类的虚函数时出现段错误
Segfault when calling virtual function of derived class
当我调用派生类的虚函数时,我一直有段错误的问题。但是,如果我将函数的名称更改为与基类中的虚函数的名称不同,则不会发生这些段错误。下面是一些代码:
//in main
//initialize scene objects
//camera
if((camera = (Camera*)malloc(sizeof(Camera))) == NULL){
cout << "Could not allocate memory for camera" << endl;
}
//...code in middle
//inside file parsing...
//infile is an ifstream
//nextString is a char*
if(!strcmp(nextString,"camera")){
camera->parse(infile); //segfault here
}
下面是基类头文件(.cpp只在构造函数中实例化变量):
class WorldObj{
public:
WorldObj();
~WorldObj();
virtual void parse(ifstream&) =0;
vec3 loc; //location
};
下面是Camera类中的代码,我用它来编写虚函数:
void Camera::parse(ifstream &infile){
//do parsing stuff
}
parse()在头文件中声明为virtual void parse(ifstream&);
我这里的问题是,如果我重命名parse()中的相机类似CameraParse()的东西,并完全忽略了有一个虚拟函数要实现的事实,代码工作完全正常!
你能解释一下为什么调用虚函数会导致段错误吗?我已经检查了Valgrind,看看是否有任何内存问题,它告诉我有一个无效的读/写8字节。我明白这意味着我没有为我的对象正确分配内存,但我不知道我在分配方面出了什么问题。
任何帮助都将是感激的:)
你不能(仅仅)malloc
一个非pod对象,你必须new
它。
这是因为malloc
保留了适量的空间,但没有构造对象,这对于任何具有虚函数的类来说都是非常重要的,即使构造函数是默认的。
现在,特定的问题只在进行虚函数调用时出现,因为这取决于new
执行的额外初始化,但是使用任何非pod类型的未构造实例仍然是错误的。
请注意,我使用POD (Plain Old Data)作为仅具有简单初始化的任何内容的惰性简写。一般来说,如果类(或结构)及其任何成员或基类都没有执行操作的构造函数,则类(或结构)可以简单地初始化。出于我们的目的,每个具有一个或多个虚方法的类(即使它们是继承的,或者在数据成员中)都需要进行重要的初始化。
具体来说,Ben Voigt回答中的标准引用描述了对象生命周期开始的两个阶段(在此期间您可以安全地进行方法调用,特别是虚方法调用):
- 为T型获得正确对齐和大小的存储,
当你调用malloc
当您使用
- 如果对象具有非平凡初始化,则其初始化完成
new
时,只在非平凡初始化类型中出现
作为参考,这是最接近您现有代码的正常用法:
Camera *camera = new Camera;
// don't need to check for NULL, this will throw std::bad_alloc if it fails
camera->parse(file);
// don't forget to:
delete camera;
这是更好的风格:
std::unique_ptr<Camera> camera(new Camera);
camera->parse(file);
// destruction handled for you
并且仅当确实需要使用malloc
或其他特定的分配器时:
Camera *camera = (Camera *)malloc(sizeof(*camera));
new (camera) Camera; // turn your pointer into a real object
camera->parse(file);
// destruction becomes uglier though
camera->~Camera();
free(camera);
malloc
不调用构造函数
你必须改变(c++创建对象的方式)
camera = (Camera*)malloc(sizeof(Camera)))
camera = new Camera; // Now you camera object will be created and constructed.
Useless提供了正确的解释。以下是标准(第3.8节)中的要求:
对象的生存期是对象的运行时属性。如果对象是类类型或聚合类型,并且它或它的一个成员是由普通默认构造函数以外的构造函数初始化的,则该对象被称为具有非平凡初始化。[注:普通复制/移动构造函数的初始化是非普通初始化。]
类型为
T
的对象的生存期开始于:
为
T
类型获得合适的对齐和大小的存储器,和如果对象具有非平凡初始化,则表示初始化完成。
类型为
T
的对象的生存期结束于:
如果
T
是具有非平凡析构函数的类类型,则开始析构函数调用,或者对象占用的存储空间被重用或释放。
使用new,而不是malloc。您分配了内存,但没有创建对象。使用new和相应的构造函数创建虚拟函数调度表,然后才能使用它。例如:
if((camera = new (nothrow) Camera()) == NULL){
cout << "Could not allocate memory for camera" << endl;
}
if(!strcmp(nextString,"camera")){
camera->parse(infile); //segfault here
}
也可以使用简单的
camera = new Camera;
并在某处捕获可能的异常bad_alloc
- 编写代码时C++出现错误:错误 1 错误 C2601:'circle':本地函数定义是非法的
- 如何摆脱C ++中的分段错误错误?
- Clang 8 带有静态 constexpr 和数组的链接器错误 - 错误是什么以及如何解决它?
- 为什么每当我尝试运行此链接列表删除功能时都会收到分段错误错误?
- 如何解决分段错误错误C++
- 作为参数模板的模板类:MSVC 错误 - 错误 C2977:模板参数过多 (C++98)
- 安卓工作室 |CPP 文件错误错误: 位图库中对"AndroidBitmap_unlockPixels"的未定义引用
- 卷曲给出分段错误错误
- 无法访问 Arduino 结构字段。错误"退出状态 1。xxxx 不命名类型"
- 错误错误 C2872:"布尔值":kinect.h 的不明确符号
- C++打印模板容器错误(错误:"运算符<<"的不明确重载)理解?
- 结构的分割错误错误
- 为什么此代码返回分段错误错误?
- 错误错误:无法编译内置功能
- 分段错误错误C++
- C++ 1Z 错误:错误:演绎指南中声明中的显式限定
- 使用对数据类型的向量的哈希表中的分段错误错误
- 为什么此代码会导致分段错误错误
- JNA结构字段值错误
- C++段故障错误