tags:

views:

272

answers:

4

Debugging some code in Visual Studio 2008 (C++), I noticed that the address in my function pointer variable is not the actual address of the function itself. This is an extern "C" function.

int main() {
   void (*printaddr)(const char *) = &print; // debug shows printaddr == 0x013C1429

}

Address: 0x013C4F10
void print() {
  ...
}

The disassembly of taking the function address is:

   void (*printaddr)(const char *) = &print;
013C7465 C7 45 BC 29 14 3C 01 mov         dword ptr [printaddr],offset print (13C1429h) 

EDIT: I viewed the code at address 013C4F10 and the compiler is apparently inserting a "jmp" instruction at that address.

013C4F10 E9 C7 3F 00 00   jmp         print (013C1429h) 

There is actually a whole jump table of every method in the .exe.

Can someone expound on why it does this? Is it a debugging "feature" ?

+2  A: 

Ah, I viewed the code at address 013C4F10 and the compiler is apparently inserting a "jmp" instruction at that address.

013C4F10 E9 C7 3F 00 00   jmp         print (013C1429h)

There is actually a whole jump table of every method in the .exe.

When I switch to release mode the jump table goes away and the address is indeed the actual function address.

Can someone expound on why it does this? Is it a debugging "feature" ?

mrjoltcola
+4  A: 

I'm going to hazard a guess here, but it's possibly to enable Edit-and-Continue.

Say you need to recompile that function, you only need to change the indirection table, not all callers. That would dramatically reduce the amount of work to do when the Edit-and-Continue feature is being exercised.

Bahbar
sounds reasonable, but then the function pointer `printaddr` would still point to the old (non-edited) `print` function... perhaps there's a bug in the debugger? :)
Martin
@Martin: no, the function pointer always points to the jump table, so that when edit and continue recompiles the function, only the jump table gets modified. The function pointer value does _not_ change, ever. That's the beauty of it, really. Imagine your code stores a function pointer somewhere in memory. Edit and Continue has no way to update that. But by pointing it to a jump table, modifying the jump table catches all the potential usages of the function at once.
Bahbar
@Bahbar: that's not what the disassembly above looks like since the pointer isn't set to point at the jump table but directly to the function instead
Martin
@Martin: Doh. I guess I wanted to believe too much. Thanks for pointing it out.
Bahbar
+1  A: 

it's probably to do with the interaction between the linker, and the need to call code in DLLs

This article talks about it, I'm not 100% sure how it applied to your example but it seems like it might help you understand http://msdn.microsoft.com/en-us/library/aa271769(VS.60).aspx

John Burton
+5  A: 

That is caused by 'Incremental Linking'. If you disable that in your compiler/linker settings the jumps will go away.

http://msdn.microsoft.com/en-us/library/4khtbfyf(VS.80).aspx

RaptorFactor
That is the answer. Jump thunks. Thank you.
mrjoltcola