I have code with inheritance that looks like this:
B
/ \
/ \
/ \
BI D
(template) /
\ /
\ /
DI
(template)
[B]ase
and [D]erived
are interfaces that both contain a static
method create()
, which returns an instance of the respective implementation, BaseImpl
or DerivedImpl
.
The implementations are templates, and the factory methods choose how to instantiate them at runtime. The code below is a working example of my program's logic.
The problem is, in my real code, Base
methods get a faulty this
pointer and inevitably crash. I have examined the assembly code right before the call to one of the methods, which takes no arguments, in both real and example code, and found that it differs:
Working (example) code
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
The above translates to a base->method()
call, where base
is a std::unique_ptr<Base>
.
For those that don't know, the calling convention of class methods can be a __thiscall, which it in this case is. That means that this
isn't passed on the stack, but is stored in ecx
. The code above simply stores this
into ecx
, and then locates method()
, stores its address into edx
, and calls it. Everything works as it should.
Faulty (real) code
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
This is the exact same base->method()
call. The address of method()
is stored into ebx
this time. this
, however, is loaded from an arbitrary place off the stack!? The program, as expected, crashes. Anyone knows why would the compiler generate assembly like that? I'm still trying to figure it out.
Code
The example code is below. The real code crashes at a point analogous to the example's call to base->check()
from invoker->invoke()
.
Code removed to conserve space. To view it, check the edit history.