Having been a long time user of Microsoft Visual C++ .Net 2003 (MSVC), I've recently been using g++ on a project. I've found a difference between the two compilers when calling a virtual function that has me puzzled. I'm hoping someone will know the answer or point me in the right direction to find the answer.
The issue is when calling virtual functions. In MSVC the parameters are pushed on to the stack as expected and then the address of the function is loaded into EAX. Finally "call EAX" is issues to call the virtual function. In g++ (Cygwin g++ v3.4.4) the parameters are pushed onto the stack as expected, but then a pointer (32 bit pointer in my case) to the vtable is pushed on the stack as well then finally EAX is loaded with the address of the function. - Why does g++ load a pointer to the vtable on the stack after pushing on the params? - Is there a compiler option that can be used to avoid putting a pointer to the vtable on the stack? (I looked but couldn't find one.) Sincere thanks for your time and attention! Dev1024 Details and background material: ======================================== C++ Source Code #include <stdio.h> class ITest { public: void virtual TestFunc(int x, int y, int z) = 0; }; class Test : ITest { public: Test() {} ~Test() {} void TestFunc(int x, int y, int z) { int a; a = x + y + z; } }; int main (void) { ITest *testptr; testptr = (ITest *) new Test(); testptr->TestFunc(1, 2, 3); delete testptr; } To build with g++: g++ -g -o myapp main.cpp In MSVC build as release to get the code below. this remove all the debug stuff Microsoft adds for error cheching. ============================================ In gdb it is disassembled as follows. Note my comments (gdb) disas Dump of assembler code for function main: 0x00401050 <main+0>: push %ebp 0x00401051 <main+1>: mov %esp,%ebp 0x00401053 <main+3>: push %ebx 0x00401054 <main+4>: sub $0x24,%esp 0x00401057 <main+7>: and $0xfffffff0,%esp 0x0040105a <main+10>: mov $0x0,%eax 0x0040105f <main+15>: add $0xf,%eax 0x00401062 <main+18>: add $0xf,%eax 0x00401065 <main+21>: shr $0x4,%eax 0x00401068 <main+24>: shl $0x4,%eax 0x0040106b <main+27>: mov %eax,0xfffffff4(%ebp) 0x0040106e <main+30>: mov 0xfffffff4(%ebp),%eax 0x00401071 <main+33>: call 0x403d50 <_alloca> 0x00401076 <main+38>: call 0x404a90 <__main> 0x0040107b <main+43>: movl $0x4,(%esp) 0x00401082 <main+50>: call 0x4022a0 <_Znwj> 0x00401087 <main+55>: mov %eax,%ebx 0x00401089 <main+57>: mov %ebx,(%esp) 0x0040108c <main+60>: call 0x404e14 <_ZN4TestC1Ev> 0x00401091 <main+65>: mov %ebx,%eax 0x00401093 <main+67>: mov %eax,0xfffffff8(%ebp) 0x00401096 <main+70>: mov 0xfffffff8(%ebp),%eax 0x00401099 <main+73>: mov (%eax),%edx //save the address of the function in EDX 0x0040109b <main+75>: movl $0x3,0xc(%esp) //push params onto stack 0x004010a3 <main+83>: movl $0x2,0x8(%esp) 0x004010ab <main+91>: movl $0x1,0x4(%esp) 0x004010b3 <main+99>: mov 0xfffffff8(%ebp),%eax //Address of the vtable is loaded into EAX 0x004010b6 <main+102>: mov %eax,(%esp) //Now it is pushed on the stack. Why??????? 0x004010b9 <main+105>: mov (%edx),%eax //Load EAX with address of virtual function 0x004010bb <main+107>: call *%eax 0x004010bd <main+109>: mov 0xfffffff8(%ebp),%eax 0x004010c0 <main+112>: mov %eax,(%esp) 0x004010c3 <main+115>: call 0x402280 <_ZdlPv> 0x004010c8 <main+120>: mov $0x0,%eax 0x004010cd <main+125>: mov 0xfffffffc(%ebp),%ebx 0x004010d0 <main+128>: leave 0x004010d1 <main+129>: ret =========================================== In MSVC it compiles as follows. Note it does not put a pointer to the vtable on the stack. int main (void) { 00401010 push esi ITest *testptr; testptr = (ITest *) new Test(); 00401011 push 4 00401013 call operator new (401044h) 00401018 add esp,4 0040101B test eax,eax 0040101D je main+19h (401029h) 0040101F mov dword ptr [eax],offset Test::`vftable' (4060ECh) 00401025 mov esi,eax 00401027 jmp main+1Bh (40102Bh) 00401029 xor esi,esi testptr->TestFunc(1, 2, 3); 0040102B mov eax,dword ptr [esi] 0040102D push 3 0040102F push 2 00401031 push 1 00401033 mov ecx,esi 00401035 call dword ptr [eax] delete testptr; 00401037 push esi 00401038 call operator delete (401108h) 0040103D add esp,4 } 00401040 xor eax,eax 00401042 pop esi 00401043 ret _______________________________________________ help-gplusplus mailing list help-gplusplus@gnu.org http://lists.gnu.org/mailman/listinfo/help-gplusplus