0

我的继承代码如下所示:

        B
       / \
      /   \
     /     \
    BI      D
(template) /
      \   /
       \ /
        DI
    (template)

[B]ase并且[D]erived是同时包含static方法的接口,该方法create()返回相应实现的实例,BaseImpl或者DerivedImpl。实现是模板,工厂方法选择如何在运行时实例化它们。下面的代码是我的程序逻辑的一个工作示例。

问题是,在我的真实代码中,Base方法得到一个错误的this指针并不可避免地崩溃。我在调用其中一种方法之前检查了汇编代码,该方法在实际代码和示例代码中都没有参数,发现它有所不同:

工作(示例)代码

call   <std::unique_ptr<Base, std::default_delete<Base> >::operator->() const>
mov    (%eax),%edx
add    $0x8,%edx
mov    (%edx),%edx
mov    %eax,%ecx
call   *%edx

以上转换为base->method()调用,其中basea 是std::unique_ptr<Base>. 对于那些不知道的人,类方法的调用约定可以是__thiscall,在这种情况下就是这样。这意味着它this不会在堆栈上传递,而是存储在ecx. 上面的代码只是简单地存入thisecx然后定位method(),将其地址存入edx,然后调用它。一切正常。

错误(真实)代码

call   <std::unique_ptr<Base, std::default_delete<Base> >::operator->() const>
mov    (%eax),%edx
add    $0x18,%edx
mov    (%edx),%ebx
lea    -0x24(%ebp),%edx
mov    %eax,(%esp)
movl   $0x9,-0x9c(%ebp)
mov    %edx,%ecx
call   *%ebx

这是完全相同的base->method()调用。的地址method()被存储到ebx这个时间。this但是,是从堆栈外的任意位置加载的!?正如预期的那样,该程序崩溃了。任何人都知道为什么编译器会生成这样的程序集?我仍在试图弄清楚。

代码

示例代码如下。实际代码在类似于示例调用base->check()from的点崩溃invoker->invoke()

删除代码以节省空间。要查看它,请检查编辑历史记录。

4

1 回答 1

0

这是一个错误。(55173、55367、55453)该错误特定. _ _gcc-i686-mingw4.7.04.7.2

55173 开始

当对同时使用虚拟和非虚拟继承的对象调用虚拟调用时,虚拟 thunk 会为目标函数留下无效的“this”指针。

这基本上就是我在问题中描述的内容。应该保存的寄存器this用于不相关的操作。

唯一的解决方案是降级到以下4.7.0或升级到4.7.3或以上。

于 2013-09-30T02:33:52.133 回答