Grazie alla sua incomparabile efficienza, seconda solo al linguaggio assembler, questo linguaggio è uno strumento, fino a ieri senza alternative, con cui sono stati realizzati sistemi operativi, sistemi di database, procolli di rete, e molti altri componenti software.
Ma chi ha avuto una significativa esperienza di programmazione in linguaggio C sa bene quanti e quali tranelli questo linguaggio pone sulla tormentata strada di chi lo utilizza.
Riguardo alla memory safety in particolare, la difficoltà sta nel bilanciare esattamente le chiamate alle funzioni malloc e free, che servono rispettivamente a allocare e rilasciare aree di memoria.
Una programmazione meno che perfetta provoca problemi dai nomi evocativi, come memory leak, double free e dandling pointer, vere bombe a orologeria celate all'interno di un software.
Con questo linguaggio, evoluzione del precedente, e con l'utilizzo della Standard Template Library, la programmazione diventa molto più facile e sicura, se ci si limita all'utilizzo di tipi standard come le stringhe e le varie collezioni di oggetti.
Per il resto il problema si sposta solo più in là, all'allocazione e rilascio di oggetti, con gli operatori new e delete. Anche in questo caso deve esserci un esatto bilanciamento. Ci vuole molta attenzione e disciplina, e l'utilizzo di particolari strategie (come RAII) per non cadere in errore.
Il linguaggio Rust si propone come moderna alternativa, vantando il mantenimento di un'elevata efficienza, e nel contempo offrendo un meccanismo (borrow checker) per assicurare la memory safety.
Questo tipo di linguaggi offre un meccanismo automatico di rilascio della memoria allocata e non più utilizzata, la qual cosa non è solamente più semplice per chi programma, ma anche decisamente più sicura.
I primi esempi di garbage collection risalgono al 1959 per il linguaggio LISP. Ora, tutti i moderni linguaggi di alto livello, che siano di scripting o di programmazione, hanno questo tipo di meccanismo.
Purtroppo, la memoria non è l'unica risorsa che richiede il rispetto del ciclo alloca-utilizza-restituisci, oppure apri-utilizza-chiudi. La medesima regola vale anche per i file, le connessioni di rete, i thread, le risorse grafiche, i timer, gli oggetti di tipo event listener e observer, e via dicendo. E a cascata, questo si riverbera su ogni oggetto che utilizza risorse di questo tipo.
Ogni linguaggio moderno ha qualche meccanismo per alleviare questo tipo di gestione, come la parola chiave Using e l'interfaccia IDisposable in C#, oppure l'interfaccia AutoCloseable in Java.
Giorgio Barchiesi
Albo degli Ingegneri Sez. A, N. 4027 della Prov. di Trento
P.IVA 02370260222, C.F. BRC GRG 58L26 C794R
Copyright © 2015-2024 Giorgio Barchiesi - Tutti i diritti riservati