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:

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):

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++:

#include <iostream>

using namespace std;

int main(){
    
	char x = 'a';
	void* p = (void*) &x;
	double* d = (double*) p;
	
	cout << x << endl << *d << endl;

	// output:
	// a
	// 2.8477e-306

	return 0;
}

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:

  1. 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.);
  2. linguaggi quasi sicuri, come il Pascal, che fa quasi tutti i controlli tranne alcuni relativi ai dangling pointers;
  3. 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.

Bibliografia

Voci correlate

  Portale Informatica: accedi alle voci di Wikipedia che trattano di Informatica