4 ms·
What happens if sum is a virtual function? Or does it not matter? I am not too familiar with c++ casting magic.
by wbkang 11y ago
What happens if sum is a virtual function? Or does it not matter? I am not too familiar with c++ casting magic.
- stormbrew 11y agoMost likely you'll get a segfault when it tries to read from page 0 to get to the class' vtable (which is where the references to the virtual functions live).
- jrziviani 11y agoYes, you'll get a segmentation fault, consider this code, compiled with debug information: #include <iostream> using namespace std; class myclass { public: virtual int sum(int a, int b) { return a + b; } }; int main() { myclass test; cout << test.sum(1, 2) << endl; cout << ((myclass*)0)->sum(10, 11) << endl; return 0; } Debugging: (gdb) b main Breakpoint 1 at 0x4008ae: file test.cpp, line 16. (gdb) run Starting program: /tmp/test Breakpoint 1, main () at test.cpp:16 16 myclass test; (gdb) ni 17 cout << test.sum(1, 2) << endl; (gdb) info vtbl test vtable for 'myclass' @ 0x400a30 (subobject @ 0x7fffffffe410): [0]: 0x400974 <myclass::sum(int, int)> Notice that the function address to be called is not know at compile time, the compiler wrote a lookup table, named vtable, to know which function it will call based on the class instance. (gdb) disassemble main [snip] 0x00000000004008ae <+8>: movq $0x400a30,-0x10(%rbp) ; see the vtable address here => 0x00000000004008b6 <+16>: lea -0x10(%rbp),%rax ; ohh, the vtable address is the 'myclass test' instance* 0x00000000004008ba <+20>: mov $0x2,%edx 0x00000000004008bf <+25>: mov $0x1,%esi 0x00000000004008c4 <+30>: mov %rax,%rdi ; pass this to RDI 0x00000000004008c7 <+33>: callq 0x400974 <myclass::sum(int, int)> * it means that the first (and only one, in this case) field of my myclass is that vtable. (gdb) print test $1 = {_vptr.myclass = 0x400a30 <vtable for myclass+16>} (gdb) info register rax rax 0x7fffffffe410 140737488348176 (gdb) x/x 0x7fffffffe410 0x7fffffffe410: 0x00400a30 (gdb) x/x 0x00400a30 0x400a30 <_ZTV7myclass+16>: 0x00400974 Then, the compiler knows that it must call '[0]: 0x400974 <myclass::sum(int, int)>' function. Compare with: ((myclass*)0)->sum(10, 11) 0x00000000004008e5 <+63>: mov $0x0,%eax ; vtable address is 0 :( 0x00000000004008ea <+68>: mov (%rax),%rax ; the address to RAX is 0, and we cannot access that segment of memory - BOOOM 0x00000000004008ed <+71>: mov (%rax),%rax 0x00000000004008f0 <+74>: mov $0xb,%edx 0x00000000004008f5 <+79>: mov $0xa,%esi 0x00000000004008fa <+84>: mov $0x0,%edi 0x00000000004008ff <+89>: callq *%rax