2009-02-28 16 views
13

Dato che tutti i tipi di dati primitivi e gli oggetti hanno allocata memoria, è intuitivamente facile immaginare i puntatori a questi tipi.Dove puntano esattamente i puntatori funzione?

Ma dove puntano esattamente i puntatori di funzione? Dato che le istruzioni vengono convertite in codice macchina e risiedono in memoria, dovremmo considerare che puntano alla posizione di memoria corrispondente all'inizio delle istruzioni delle funzioni?

Affrontiamo molti errori nei puntatori a causa dell'accesso illegale alla memoria. È il caso che si verifichino degli errori quando i puntatori di funzione puntano alla memoria dati invece della memoria istruzioni?

+0

Stai vedendo gli accessi illegali alla memoria sui puntatori di funzione o su altri puntatori? –

+0

Che cosa significa "ci troviamo di fronte a molti errori nei puntatori a causa di un accesso illegale alla memoria"? Come si verificano questi errori? Quali sono questi errori? –

+0

@Steve No @ S.Lot Mi riferivo agli errori che si ottengono quando inizializziamo int * in un po 'di spazzatura che è un indirizzo di memoria protetto. –

risposta

29

Il puntatore di funzione punta anche alla memoria, l'unica differenza è che esiste un codice eseguibile in quella posizione di memoria anziché dati.

Su molte piattaforme, se si tenta di eseguire dati (ad es. Memoria normale) si arresta in modo anomalo o si verifica un'eccezione. Questo è noto come Prevenzione dell'esecuzione dei dati: una misura di sicurezza che impedisce alle applicazioni di eseguire inavvertitamente il codice dodgy che può essere inserito dal malware.

+0

E penso che prima di iniziare l'esecuzione, la cornice delle funzioni correlate sia inizializzata. Ad esempio, richiamare stack operand specifici e array di variabili locali (con argomenti passati) del creato. – zgulser

4

È un puntatore del codice. Indica l'indirizzo della funzione. È essenzialmente come hai descritto. E sì, se hai dei puntatori che non indicano ciò che ti aspetti, avrai dei problemi.

-3

Beh, non sono sicuro, ma considerando che le funzioni sono istruzioni (ADD, SUB, JMP) e che ognuna di esse ha valori esadecimali, credo che non si cambi la funzione ma solo l'istruzione JMP(). ..

+1

Se si sta modificando l'istruzione JMP, si ha codice auto-modificante, che di solito è considerato magia nera. I puntatori alle funzioni sono come gli altri puntatori: un indirizzo memorizzato nella RAM; il JMP ottiene il target dalla variabile anziché i dati compilati nel programma. –

+0

Penso che ci siano alcune CPU che fanno tutti i puntatori in questo modo, avendo il "puntatore" un valore nel codice, per esempio PIC e DSP molto semplici. –

+0

Non capisco, dov'è il difetto nella mia linea di pensiero? – Diones

2

I puntatori di funzione indicano lo address of the function nella memoria.

In base al modo in cui vengono normalmente assegnati i puntatori di funzione, sarei sorpreso se li avessi puntato a un percorso dati. In genere non sono espressi e quindi è improbabile che puntino in un punto diverso da una funzione valida. Se li lanci molto, questo potrebbe essere un problema. È più probabile, tuttavia, che i dati che stai trasmettendo alla funzione siano errati.

2

Un puntatore a funzione contiene l'indirizzo di una funzione, indipendentemente dal significato di un determinato sistema. È possibile utilizzarlo per chiamare la funzione indirettamente, è possibile assegnare e confrontare i valori del puntatore della funzione. È inoltre possibile convertire un puntatore a funzione in un altro tipo puntatore-a-funzione e così via.

Il modo più semplice per un compilatore di implementare un puntatore a funzione è l'indirizzo di memoria della funzione e la maggior parte dei compilatori lo fa in questo modo, ma lo standard di lingua non lo specifica. Alcuni sistemi (penso che l'AS/400 di IBM sia un esempio) memorizzano informazioni aggiuntive nei puntatori di funzione. Un compilatore può implementare i puntatori di funzioni come indici interi in una tabella di descrittori, purché la semantica richiesta sia implementata correttamente.

Non è possibile annullare la ricerca di un puntatore a funzione. Una chiamata di funzione richiede un puntatore, non un nome di funzione, come espressione di prefisso; se si utilizza un nome di funzione, tale nome viene convertito implicitamente in un puntatore (per quanto riguarda la lingua, il codice macchina generato potrebbe essere diverso). Quindi non esiste un modo portatile per un programma per rilevare se i puntatori di funzione contengono effettivamente indirizzi di memoria o meno.

non-portabile, data una funzione func, si può fare qualcosa di simile:

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

e ti probabilmente vedere qualcosa che assomiglia a una rappresentazione leggibile di un indirizzo di memoria.Ma in senso stretto, il comportamento della conversione del puntatore alla funzione void* non è definito dalla lingua e potrebbe non funzionare su alcuni sistemi.

È possibile che sia in grado di convertire un puntatore a unsigned char* ed esaminare il codice macchina della funzione, ma va ben oltre quanto definito dallo standard C.

È consigliabile trattare i puntatori di funzione come valori opachi che fanno riferimento a funzioni particolari in un modo non specificato.

Problemi correlati