2012-01-18 16 views
19

Dado el conocimiento del prototipo de una función y su dirección en la memoria, es posible llamar a esta función desde otro proceso o algún código que no conoce más que el prototipo y la dirección de memoria? Si es posible, ¿cómo se puede manejar un tipo devuelto en el código?Llamar a una función a través de su dirección en la memoria en c/C++

+0

proceso? o hilo? – Cyan

+0

En C++ no hay procesos. Debes especificar tu plataforma si quieres ayuda con eso. –

+0

¿De otro proceso? Ese es un caso muy especial. ¿En serio necesitas eso? – jalf

Respuesta

36

En los sistemas operativos modernos, cada proceso tiene su propio espacio de direcciones y direcciones sólo son válidos dentro de un proceso. Si desea ejecutar código en algún otro proceso, que o bien tienen que inyectar una biblioteca compartida o adjuntar su programa como un depurador.

Una vez que esté en el espacio de direcciones del otro programa, este código invoca una función en una dirección arbitraria:

typedef int func(void); 
func* f = (func*)0xdeadbeef; 
int i = f(); 
+4

Gracias a @ R.Martinho por el [mejor estilo para los prototipos de función typedef] (http://chat.stackoverflow.com/transcript/message/2400130#2400130). ¡Ni siquiera sabía que esto funciona! – sbi

+0

Muy agradable. Este método es mucho más fácil que usar el ensamblaje en línea si el objetivo también es el proceso C. +1 para ti. –

+0

AFAIK, no hay forma de * escribir * memoria en el espacio de direcciones de otros programas en los nuevos sistemas operativos y eso causa un SEGFAULT. Pero no hay nada que impida que un programa lea cualquier ubicación de la memoria (por lo tanto, el error heartbleed da miedo en OpenSSL, ya que puede leer cualquier cosa en la memoria con eso). Entonces, ¿podría explicar por qué no puedo acceder al espacio de direcciones de otro programa y necesito bibliotecas compartidas o depurador? –

11

Sí, está describiendo un puntero de función. Aquí hay un ejemplo simple;

int (*func)(void) = (int (*)(void))0x12345678; 
int x = func(); 

Probablemente no funcione entre procesos: en la mayoría de los sistemas operativos, los procesos no tienen acceso a la memoria de los demás.

+0

¿Por qué lanzar a void (*) (void) para asignar un int (*) (void)? Eso es bastante ilógico, ¿no? – Geoffroy

+0

@Geoffroy - typo. Y arreglado incluso antes de comentar ... –

+2

@CarlNorum: Dichos errores ocurren cuando eres demasiado flojo para escribir un 'typedef'. ':)' – sbi

1

En la mayoría OP, cada proceso tiene su propia memoria, por lo que se puede' t.

Código de ejemplo: A.C.:

#include <stdio.h> 

int r() {return 2;} 
int main() { 
    printf("%p\n",r); 
    while(1); 
} 

b.c:

#include <stdio.h> 

int main() { 
int a,(*b)(); 
scanf("%p",&b); 
a=b(); 
printf("%d\n",a); 
return 0; 
} 

este conseguir fallo de segmentación.

+0

En c c + + puede acceder a cualquier ubicación de memoria que desee, para bien o para mal – dtech

+0

@ddriver: C++ le permite acceder a cualquier ubicación _virtual_ de memoria. Sin embargo, muchos sistemas operativos le dan a cada proceso su propia memoria virtual, por lo que no pueden afectarse entre sí. Sin embargo, hay llamadas específicas del sistema operativo que puede hacer/usar para afectar otra memoria de procesos. –

+3

@ddriver - no, no puedes. Solo puede acceder a las ubicaciones de memoria a las que el sistema operativo le permite acceder. Todo lo que su programa sabe es el entorno de memoria virtual en el que se está ejecutando, que normalmente no tiene relación con la realidad física. –

1

Todas las respuestas anteriores son agradable, pero demasiado tiempo ;-):

int i = ((int (*)(void))0xdeadbeef)(); 
+1

No, fueron geniales. La tuya, por otro lado, es muy pobre. Sin explicaciones en absoluto. –

+1

Es un trazador de líneas agradable – BullyWiiPlaza

1

cuando se necesita una llamada directa:

((void(*)(void))0x1234)(); 
Cuestiones relacionadas