ifo*_*e2d 5 c++ inheritance vtable box2d mingw32
我想知道是否有任何C++专家可以对这种奇怪的情况有所了解.Box2D物理引擎附带的一个示例是消息"称为纯虚方法",但仅限于某个编译器(并且仅在发布版本中).
您可能知道Box2D是一个非常可靠的代码块,所以我认为这可能是编译器的问题,特别是考虑到它只发生在这个特定的编译器上.我在Windows7上使用mingw32:
> gcc.exe --version
gcc version 4.4.0 (GCC)
Run Code Online (Sandbox Code Playgroud)
以下是Box2D相关部分的简要摘录.您可以在以下网址查看完整资料来源:
b2Shape.h
b2CircleShape.h
b2CircleShape.cpp
SensorTest.h
//base class
class b2Shape
{
public:
virtual ~b2Shape() {}
virtual b2Shape* Clone(b2BlockAllocator* allocator) const = 0;
};
//sub class
class b2CircleShape : public b2Shape
{
public:
b2CircleShape();
b2Shape* Clone(b2BlockAllocator* allocator) const;
};
inline b2CircleShape::b2CircleShape() {}
b2Shape* b2CircleShape::Clone(b2BlockAllocator* allocator) const
{
void* mem = allocator->Allocate(sizeof(b2CircleShape));
b2CircleShape* clone = new (mem) b2CircleShape;
*clone = *this;
return clone;
}
Run Code Online (Sandbox Code Playgroud)
请注意克隆功能中的新位置.
现在导致问题的执行归结为:
{
b2CircleShape shape;
shape.Clone(allocator); //ok
}
{
b2CircleShape shape;
shape.Clone(allocator); //"pure virtual method called"
}
Run Code Online (Sandbox Code Playgroud)
在教育了我自己如何调用虚拟方法之后,我试图弄清楚它为什么会在这里发生,因为它不适合在基类构造函数中调用虚函数的经典情况.经过长时间盲目磕磕绊绊之后,我想出了上面的最小案例.
我的猜测是编译器足够聪明,可以看到这两个b2CircleShape实例在同一范围内没有使用,所以它只为一个分配空间并重用它.在第一个实例被破坏后,vtable如预期的那样被冲洗.然后由于某种原因,当构建第二个实例时,vtable不再构造......?
我想出了两个可以避免这个问题的东西,但就像我说它似乎更像是一个编译器问题所以我并不是说这个代码需要改变.
可疑的修复号1是注释掉基类中的虚拟析构函数定义.我在这个问题上阅读的所有信息都表明这不是答案.(有趣的是,我发现仅仅从基类析构函数中删除'virtual'修饰符是不够的.我的理解是编译器会提供默认的析构函数~b2Shape(){}如果没有指定,那么为什么结果不同如果我实际上指定了默认值是什么?嗯,这是真正的... ...
我发现的不太可疑的修复2是从子类构造函数中删除'inline'.也许有一些关于放置新的内联构造和重复使用的实例在同一堆栈框架中不能很好地一起使用.(更新:进一步检查显示新的展示位置无关紧要)
更多的研究告诉我,编译器可以自由地做任何关于"内联"建议的事情,所以也许其他编译器没有这个问题,因为他们忽略了'内联'?
小智 1
这是显而易见的。
A)如果它按预期工作一次那就没问题了。B) 错误再次发生的事实只能意味着它是您的 gcc 中的错误。是的,这些东西确实可能有错误。我在除 MSVC 编译器之外的所有编译器中都发现了错误。
如果您获取 GCC 或 Clang 或其他任何内容的代码并找到错误发生的位置,则该错误将是由于它读取的某些标志造成的。如果它工作一次然后再次失败,则编译器数据中的标志或位已更改,这意味着编译器中存在内存溢出或其他拼写错误。
对不起。
归档时间: |
|
查看次数: |
413 次 |
最近记录: |