2010-03-21 11 views
19

Debugging einige Code in Visual Studio 2008 (C++), bemerkte ich, dass die Adresse in meinem Funktionszeiger Variable ist nicht die tatsächliche Adresse der Funktion selbst. Dies ist eine externe "C" -Funktion.Adresse der Funktion ist nicht tatsächliche Code-Adresse

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

} 

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

Die Demontage der Funktionsadresse zu nehmen ist:

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

EDIT: I den Code an Adresse betrachtet 013C4F10 und die Compiler anscheinend an dieser Adresse eine "jmp" Instruktion eingefügt wird.

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

Es gibt tatsächlich eine ganze Jump-Tabelle für jede Methode in der .exe.

Kann jemand erklären, warum es das tut? Ist es ein Debugging- "Feature"?

+1

Hmm, was Sie die Adresse des 'print' erzählt ist' 0x013C4F10'? Mit Blick auf die Disassemblierung scheint die Adresse des Ausdrucks tatsächlich '0x013C1429' zu sein und der Wert wird in' printaddr' gespeichert. – Martin

+0

Die Disassemblierung in Visual Studio zeigt den Ausdruck an Adresse 0x013C4F10 – codenheim

+0

@Martin: Wenn ich die Sprungtabelle in den Freigabemodus umschalte geht weg und die Adresse ist tatsächlich die eigentliche Funktionsadresse. – codenheim

Antwort

2

Der Compiler fügt eine Anweisung "jmp" an dieser Adresse in die reale Methode ein.

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

Es gibt tatsächlich eine ganze Sprungtabelle von jeder Methode in der .exe.

Es ist eine Debugging-Funktion. Wenn ich in den Freigabemodus umschalte, verschwindet die Sprungtabelle und die Adresse ist tatsächlich die tatsächliche Funktionsadresse.

6

Ich werde hier eine Vermutung riskieren, aber es ist möglicherweise zu aktivieren Edit-and-Continue.

Angenommen, Sie müssen diese Funktion neu kompilieren, Sie müssen nur die Umleitungstabelle ändern, nicht alle Anrufer. Das würde den Arbeitsaufwand drastisch reduzieren, wenn die Edit-and-Continue-Funktion ausgeführt wird.

+0

klingt vernünftig, aber dann würde der Funktionszeiger 'printaddr' immer noch auf die alte (nicht editierte)' print' Funktion zeigen ... vielleicht gibt es einen Bug im Debugger? :) – Martin

+0

@Martin: Nein, der Funktionszeiger zeigt immer auf die Sprungtabelle, so dass beim Editieren und Fortsetzen der Neukompilierung der Funktion nur die Sprungtabelle geändert wird. Der Wert des Funktionszeigers ändert sich _not_ niemals. Das ist das Schöne daran. Stellen Sie sich vor, Ihr Code speichert einen Funktionszeiger irgendwo im Speicher. Edit and Continue hat keine Möglichkeit, das zu aktualisieren. Wenn Sie jedoch auf eine Sprungtabelle zeigen, werden durch das Ändern der Sprungtabelle alle potenziellen Verwendungen der Funktion sofort erfasst. – Bahbar

+0

das ist nicht das, was die obige Disassemblierung aussieht, da der Zeiger nicht auf den Sprungtisch zeigt, sondern direkt auf die Funktion – Martin

1

es ist wahrscheinlich mit der Wechselwirkung zwischen dem Linker und der Notwendigkeit, rufen Sie Code in DLLs

Dieser Artikel spricht darüber, ich bin nicht 100% sicher, wie es angewendet Ihrem Beispiel zu tun, aber es scheint, wie es könnte Ihnen helfen zu verstehen http://msdn.microsoft.com/en-us/library/aa271769(VS.60).aspx

Verwandte Themen