# Sicurezza rispetto ai tipi

In informatica la sicurezza rispetto al tipo (in inglese type safety) è la misura con cui un linguaggio di programmazione previene o avvisa rispetto agli errori di tipo.

## Errori di tipo

Un errore di tipo è un comportamento errato o non desiderabile del programma causato da una discrepanza tra diversi tipi di dato riguardo alle costanti, variabili e metodi (funzioni) del programma.
I possibili errori di tipo sono i seguenti:
* invocare una funzione con tipi di dato errati (es: add_int(3, 4.5); );
* andare oltre i limiti di un array (out of bound);
* dangling pointer;
* invocare o mandare messaggi ad un metodo inesistente di un oggetto;
* accedere ad un campo dati inesistente di un oggetto.
Un linguaggio è considerato essere type safe se tutti gli errori di tipo vengono rivelati sempre, a compile-time (meglio) o almeno a run-time tramite adeguati controlli.
A volte la type safety è considerata alternativamente come una proprietà di un programma piuttosto che del linguaggio in cui il programma è stato scritto; ovvero, alcuni linguaggi hanno delle caratteristiche di type safeness che possono essere eluse dai programmatori che adottano pratiche poco type safe.

## Controllo del tipo

Il controllo dei tipi e del loro corretto utilizzo può quindi avvenire in compilazione (compile-time) o in esecuzione (run-time):
* se fatto a compile-time, esso produce un elaborato già controllato e quindi senza controlli a run-time. Ciò permette un'esecuzione più veloce del programma, a fronte di controlli più severi e limitanti;
* se fatto a run-time, il programmatore ha più libertà ma i controlli vengono eseguiti solo se una porzione di codice viene eseguita. Se un ramo dell'esecuzione del programma che contiene un errore di tipo non viene mai visitato, quello può nascondere un errore che potrebbe emergere in altri utilizzi del programma.

## Memory safety

La type safety è collegata alla memory safety, una restrizione della possibilità di copiare arbitrariamente dei bit di memoria da una locazione ad un'altra. Per esempio, il seguente codice C++:
Fa un'evidente violazione di tipo, in quanto crea inizialmente una variabile char, creando poi un puntatore vuoto che ci punta e facendo un cast a double, cambia il tipo del puntatore. Successivamente, ci accede e ne stampa il valore. Come prevedibile, l'output non ha senso (e varia per ogni esecuzione) in quanto una variabile di tipo char è allocata come 1 byte sullo stack mentre una variabile di tipo double necessita di 8 byte, oltre ad essere di tipo non compatibile.
Per questo motivo, è considerato indispensabile per un linguaggio avere dei meccanismi di gestione della memoria automatici, come il Garbage Collector o altri meccanismi che eseguono a compile-time come ARC per Objective-C, per evitare l'accesso a variabili già deallocate o accessi tipo quello visto prima.

## Categorie di linguaggi

I linguaggi si dividono quindi solitamente in tre categorie:
* linguaggi non sicuri come C e C++ che permettono di fare esplicitamente degli errori di tipo (per esempio, tramite cast o con i dangling pointers, etc.);
* linguaggi quasi sicuri, come il Pascal, che fa quasi tutti i controlli tranne alcuni relativi ai dangling pointers;
* linguaggi sicuri, come Smalltalk o Java che fanno tutti i controlli di tipo richiesti.
Essere un linguaggio sicuro o safe impone quindi maggiori vincoli e maggiore sicurezza nella creazione del programma. Di contro però, ci possono essere problematiche legate all'efficienza (dovendo aumentare i controlli a run-time) e all'impossibilità di gestire l'allocazione della memoria e il momento di distruzione degli oggetti, che (per certa categoria di applicazioni) possono finire col saturare l'heap.