ProgrammazioneSviluppatore Embedded C

Descrivi come vengono implementate e funzionano le funzioni di callback nel linguaggio C. Come dichiarare e utilizzare correttamente tali funzioni durante lo sviluppo di librerie o interazioni con API?

Supera i colloqui con l'assistente IA Hintsage

Risposta

Le funzioni di callback (callbacks) sono funzioni il cui indirizzo viene passato come argomento a un'altra funzione. Questo consente di implementare gestori di eventi, algoritmi personalizzati e plugin.

Dichiarazione di una funzione callback:

  1. Si descrive il tipo corrispondente di puntatore a funzione:
typedef void (*callback_func_t)(int);
  1. Passaggio della funzione gestore:
void process(callback_func_t cb) { // ... cb(42); // chiamata della callback } void handler(int n) { printf("Numero elaborato: %d\n", n); } int main() { process(handler); return 0; }

Suggerimenti:

  • Attenersi a typedef espliciti per i tipi di puntatori, il codice diventerà più leggibile.
  • Assicurati che la firma della funzione callback corrisponda a quella attesa.
  • Evita di passare funzioni locali non inizializzate o liberate.

Domanda ingannevole

È possibile passare una funzione con una firma non corrispondente come callback?

Risposta errata comune: «Sì, C lo permetterà se dichiari un esplicito casting».

Risposta corretta: Anche se il casting formale è possibile, la chiamata di tale funzione porterà a comportamenti indefiniti — valori errati possono essere passati ai parametri, lo stack potrebbe essere danneggiato.

Esempio di pericolo:

typedef void (*cb_t)(int); void wrong_cb(double d) { printf("%f\n", d); } void call(cb_t f) { f(123); } int main() { call((cb_t)wrong_cb); } // PERICOLO: le firme differiscono

Esempi di errori reali a causa della mancanza di conoscenza delle sottigliezze del tema


Storia

In un progetto embedded, la funzione di ordinamento riceveva come funzione di confronto un puntatore a una funzione con una firma troppo ristretta. Questo ha portato a errori di ordinamento e danneggiamento della memoria a causa di un passaggio errato di parametri.

Storia

In una libreria di motore grafico è stato implementato un meccanismo di eventi basato su callback, ma alcune callback facevano riferimento accidentalmente a funzioni locali di librerie dinamiche già liberate, causando crash quando si incontravano indirizzi non validi.

Storia

Durante lo sviluppo di un sistema cross-platform, l'autore ha definito in modo errato la calling convention per le funzioni callback. Questo non si manifestava in un sistema operativo, ma portava al crash del programma su un altro durante la chiamata di callback dalla libreria C.