ntx*_*ntx 14 c++ visual-studio
似乎我的问题是MSVC中的一个错误.我正在使用带有Service Pack 1的Visual Studio 2008,我的代码适用于GCC(在codepad.org上测试过).
有关此错误的任何官方信息?任何想法如何解决它?VS2010中是否修复了该错误?所有的见解将不胜感激.
代码:
struct Base {
Base(int i = 0) : i(i) {}
virtual ~Base() {}
virtual Base *clone() const = 0;
protected:
int i;
};
struct A : virtual public Base {
A() {}
virtual A *clone() const = 0;
};
struct B : public A {
B() {}
B *clone() const { return new B(*this); }
/// MSVC debugger shows that 'b' is for some reason missing the Base
/// portion of it's object ("Error: expression cannot be evaluated")
/// and trying to access 'b.i' causes an unhandled exception.
///
/// Note: This only seems to occur with MSVC
B(const B &b) : Base(b.i), A() {}
};
void foo(const A &elem) {
A *a = elem.clone();
if (a) delete a;
}
int main() {
A *a = new B;
foo(*a);
delete a;
}
Run Code Online (Sandbox Code Playgroud)
看起来好像编译器this在调用时没有正确调整指针A::clone.如果你删除声明A::clone然后一切正常.
深入挖掘,当你拥有时A::clone,vtable看起来像这样:
[0x0] 0x002f1136 [thunk]:B::`vector deleting destructor'`vtordisp{4294967292,0}' (unsigned int) void *
[0x1] 0x002f11e0 [thunk]:B::clone`vtordisp{4294967292,0}' (void) void *
[0x2] 0x002f12ad [thunk]:B::clone`vtordisp{4294967292,4}' (void) void *
[0x3] 0x002f12a3 B::clone(void) void *
Run Code Online (Sandbox Code Playgroud)
和foo调用elem.__vfptr[2],this错误地偏移了-4个字节.没有A::clone,vtable看起来像这样:
[0x0] 0x00ee1136 [thunk]:B::`vector deleting destructor'`vtordisp{4294967292,0}' (unsigned int) void *
[0x1] 0x00ee11e0 [thunk]:B::clone`vtordisp{4294967292,0}' (void) void *
[0x2] 0x00ee12a3 B::clone(void) void *
Run Code Online (Sandbox Code Playgroud)
和foo电话elem.__vfptr[1].这根本不会调整this(代码假设this将等于Base而不是B).
因此,看起来编译器假定这A::clone是一个新的虚方法,并且Base::clone在确定是否A需要新的虚拟表时不会覆盖,但后来其他一些代码确定A不需要虚拟表.您可以通过比较sizeof(B)或不使用新的虚函数来验证这一点:
struct A : virtual public Base {
A() {}
virtual A *clone() const = 0;
}; //sizeof(B)==16
struct A : virtual public Base {
A() {}
virtual A *clone() const = 0;
virtual const A *clone2() const { return this; }
}; //sizeof(B)==20
Run Code Online (Sandbox Code Playgroud)
所以这是一个编译器错误.
| 归档时间: |
|
| 查看次数: |
1290 次 |
| 最近记录: |