2009-02-28 8 views
13

Dado que todos los tipos de datos primitivos y los objetos tienen memoria asignada, es intuitivamente fácil imaginar los punteros a estos tipos.¿Dónde apuntan exactamente los indicadores de función?

Pero, ¿a dónde exactamente apuntan los punteros a las funciones? Dado que las instrucciones se convierten en código de máquina y residen en la memoria, ¿deberíamos considerar que apuntan a la ubicación de la memoria correspondiente al inicio de las instrucciones de las funciones?

Nos enfrentamos a muchos errores en los punteros debido al acceso ilegal a la memoria. ¿Es el caso de que se produzcan errores cuando los punteros de función apuntan a la memoria de datos en lugar de a la memoria de instrucciones?

+0

¿Ve los accesos ilegales a la memoria en los punteros a su función o en otros punteros? –

+0

¿Qué significa "nos enfrentamos a muchos errores en los punteros debido a acceso ilegal a la memoria"? ¿Cómo ocurren estos errores? ¿Cuáles son estos errores? –

+0

@Steve No @ S.Lott Me refería a los errores que obtenemos cuando inicializamos int * a alguna basura que es dirección de memoria protegida. –

Respuesta

29

El puntero de función también apunta a la memoria, la única diferencia es que hay código ejecutable en esa ubicación de memoria en lugar de datos.

En muchas plataformas, si intentas ejecutar datos (por ejemplo, memoria normal) se bloqueará o provocará una excepción. Esto se conoce como Prevención de ejecución de datos: una medida de seguridad para evitar que las aplicaciones ejecuten inadvertidamente un código dudoso que el malware pueda colocar allí.

+0

Y creo que antes de comenzar la ejecución, el cuadro de función relacionado se inicializa. Por ejemplo, llame a la pila de operandos específica y a la matriz de variables locales (con argumentos pasados) de la creada. – zgulser

4

Es un puntero de código. Apunta a la dirección de la función. Es esencialmente como lo describió. Y sí, si tiene indicadores que no apuntan a lo que espera, tendrá problemas.

-3

Bueno, no estoy seguro, pero considerando que las funciones son instrucciones (ADD, SUB, JMP) y que cada una de ellas tiene valores hexadecimales, creo que no estaría alterando la función sino solo la instrucción JMP(). ..

+1

Si está alterando la instrucción JMP, tiene el código de auto modificación, que generalmente se considera magia negra. Los punteros de las funciones son como otros punteros: una dirección almacenada en la RAM; el JMP obtiene su objetivo de la variable en lugar de los datos compilados en el programa. –

+0

Creo que hay algunas CPU que hacen todos los punteros de esta manera, haciendo que el "puntero" sea un valor en el código, PIC y DSP muy simples, por ejemplo. –

+0

No lo entiendo, ¿dónde está la falla en mi línea de pensamiento? – Diones

2

Los punteros de función apuntan a address of the function en la memoria.

Según la forma en que usualmente se asignan los punteros a las funciones, me sorprendería que los tuviera apuntando a una ubicación de datos. Normalmente no se emiten y es muy poco probable que apunten a otra parte que no sea a una función válida. Si los estás lanzando mucho, entonces esto podría ser un problema. Sin embargo, es más probable que los datos que está pasando a la función sean incorrectos.

2

Un puntero de función contiene la dirección de una función, sea lo que sea que eso signifique para un sistema dado. Puede usarlo para llamar a la función indirectamente, puede asignar y comparar valores de puntero de función. También puede convertir un puntero a otro tipo de puntero a función, y así sucesivamente.

La manera más directa para que un compilador implemente un puntero de función es como la dirección de memoria de la función, y la mayoría de los compiladores lo hacen de esa manera, pero el estándar de lenguaje no especifica eso. Algunos sistemas (creo que el AS/400 de IBM es un ejemplo) almacenan información adicional en indicadores de función. Un compilador podría implementar indicadores de función como índices enteros en una tabla de descriptores, siempre que la semántica requerida se implemente correctamente.

No es posible desreferenciar un puntero de función. Una llamada a función requiere un puntero, no un nombre de función, como expresión de prefijo; si usa un nombre de función, ese nombre se convierte implícitamente en un puntero (en lo que se refiere al lenguaje, el código máquina generado puede ser diferente). De modo que no hay una forma portátil para que un programa detecte si los punteros a las funciones realmente contienen direcciones de memoria o no.

no de forma portátil, dada una función func, se puede hacer algo como:

printf("Address of func is %p\n", (void*)func); 

y usted probablemente ver algo que se parece a una representación legible de una dirección de memoria.Pero, en sentido estricto, el comportamiento de la conversión del puntero a la función void* no está definido por el idioma, y ​​podría no funcionar en algunos sistemas.

Usted fuerza incluso ser capaz de convertir un puntero de función a unsigned char* y examinar el código máquina de la función, pero va mucho más allá de lo definido por la norma C.

Lo mejor es tratar los punteros de función como valores opacos que se refieren a funciones particulares de alguna manera no especificada.

Cuestiones relacionadas