我正在分析我们的应用程序中发生的访问冲突,因为它试图在虚函数表指向0的对象上调用虚函数。因此,我想知道在对象生命周期的哪些点上,虚函数表指针没有设置或显式设置为零?
(我们使用Visual C++ 10作为编译器。)
发布于 2012-08-01 17:33:54
当对象处于有效状态时,vtable指针永远不会为0。在构造和销毁期间,虽然对象具有抽象基类的动态类型,但vtable将指向抽象基类vtable,其将包括纯虚函数,但vtable指针本身仍将是非零的。
vtable指针唯一可以为零的时候是在构造之前或销毁之后。
发布于 2012-08-01 19:46:09
如果vtable指针真的是零,那么您可能已经使用了VC++扩展,例如:
class __declspec(novtable) Base {
public:
Base();
virtual void proc();
};在这里,__declspec(novtable)告诉编译器类不需要vtable,因为在派生类安装了自己的vtable之前,不会在该类上调用任何虚函数。如果在此之前调用Base::proc(),则可能会出现错误。
更可能的情况是vtable本身是非零的,但函数在其中的槽是零,这是因为函数是纯虚的:
class Base {
public:
virtual void proc() = 0;
};然后有人用这样的代码调用了它:
void Derived::proc() {
Base::proc();
// Derived-specific stuff here.
};这可能是因为派生的作者假设他们的覆盖需要调用基础版本,即使基础版本不存在。
无论哪种方式,找到它的一种方法是停止所有基类恶作剧,正常定义函数,并查看调用它的是什么。例如:
class Base {
public:
virtual void proc() {
assert( typeof(*this) != typeof(Base) ); // Break-point here.
}
};https://stackoverflow.com/questions/11756372
复制相似问题