2010-03-21 10 views
19

Depurando algún código en Visual Studio 2008 (C++), noté que la dirección en la variable de puntero a función no es la dirección real de la función. Esta es una función externa "C".La dirección de la función no es la dirección de código real

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

} 

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

El desmontaje de tomar la dirección de la función es:

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

EDIT: Vi el código en la dirección 013C4F10 y el compilador es aparentemente la inserción de una instrucción "JMP" en esa dirección.

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

En realidad existe una tabla de salto completa de cada método en el .exe.

¿Alguien puede explicar por qué lo hace? ¿Es una "característica" de depuración?

+1

Hmm, lo que está diciendo la dirección de '' print' es 0x013C4F10'? En cuanto al desmontaje, parece que la dirección de impresión es '0x013C1429' y ese es el valor que se almacena en' printaddr' – Martin

+0

El desmontaje en Visual Studio muestra imprimir en la dirección 0x013C4F10 – codenheim

+0

@Martin: Cuando cambio al modo de lanzamiento, la tabla de salto desaparece y la dirección es de hecho la dirección de la función real. – codenheim

Respuesta

2

El compilador está insertando una instrucción "jmp" en esa dirección en el método real.

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

En realidad, hay una tabla de salto completo de todos los métodos en el .exe.

Es una función de depuración. Cuando cambio al modo de lanzamiento, la tabla de saltos desaparece y la dirección es de hecho la dirección de la función real.

6

Voy a arriesgarme a adivinar aquí, pero es posible habilitar Edit-and-Continue.

Digamos que necesita recompilar esa función, solo necesita cambiar la tabla de direccionamiento indirecto, no todas las personas que llaman. Eso reduciría drásticamente la cantidad de trabajo que se debe hacer cuando se ejerce la función Editar y continuar.

+0

suena razonable, pero luego el puntero de función 'printaddr' aún apunta a la antigua función' print' (no editada) ... ¿tal vez hay un error en el depurador? :) – Martin

+0

@Martin: no, el puntero de función siempre apunta a la tabla de salto, de modo que cuando edite y continúe recompilando la función, solo se modifica la tabla de salto. El valor del puntero a la función _no_ cambia, nunca. Esa es la belleza de eso, realmente. Imagine que su código almacena un puntero de función en algún lugar de la memoria. Editar y continuar no tiene forma de actualizar eso. Pero al apuntarlo a una tabla de salto, modificar la tabla de salto capta todos los posibles usos de la función a la vez. – Bahbar

+0

eso no es lo que parece el desmontaje anterior ya que el puntero no está configurado para apuntar a la tabla de salto sino directamente a la función en su lugar – Martin

Cuestiones relacionadas