Durante la trasmissione di un oggetto per valore in una funzione in C++ avviene la creazione di una copia dell'oggetto tramite il costruttore di copia. Se nella classe è definito un costruttore di copia personalizzato, allora viene chiamato per inizializzare l'oggetto temporaneo-argomento della funzione. Se non è definito, viene utilizzato il compilatore predefinito, che esegue una copia a livello di bit (shallow copy).
Rischi:
Esempio:
class StringWrapper { char* data; public: StringWrapper(const char* str) { data = new char[strlen(str) + 1]; strcpy(data, str); } // Errore: shallow copy StringWrapper(const StringWrapper& other) : data(other.data) {} ~StringWrapper() { delete [] data; } }; void foo(StringWrapper s) { // ... } int main() { StringWrapper s1("hello"); foo(s1); // UB!!! return 0; }
"Cosa succede se si definisce un costruttore di copia in una classe con puntatore in questo modo:
MyClass(const MyClass &other) : data(other.data) {}? Quali conseguenze comporta?"
Risposta corretta: Tale costruttore di copia creerà un oggetto con un puntatore alla stessa area di memoria dell'oggetto copiato. Alla distruzione di entrambi gli oggetti, la memoria sarà liberata due volte (double free), il che porta a un comportamento indefinito. È necessario implementare la deep copy:
MyClass(const MyClass &other) { data = new int(*other.data); }
Storia
In un grande progetto server sono stati utilizzati contenitori di oggetti con un "array" grezzo all'interno e un costruttore di copia standard (shallow copy). Durante la trasmissione di oggetti per valore si è verificato un double free e crash dell'applicazione, catturati solo in produzione.
Storia
In una vecchia libreria C++ per la gestione delle immagini, il costruttore di copia non copiava il buffer grafico, il che portava a modificare una copia dell'immagine quando veniva modificata un'altra e a bug inaspettati nell'interfaccia.
Storia
Restituendo un oggetto per valore da una funzione in uno dei sistemi interni di archiviazione delle password, i dati venivano cancellati al momento della distruzione dell'oggetto temporaneo (shallow copy), il che portava a un oggetto reale con un puntatore azzerato, e la perdita è emersa casualmente durante un audit di sicurezza.