ProgrammazioneSviluppatore C++

Что происходит при передаче объекта класса по значению в функцию и какие подводные камни стоит учитывать при реализации копирующего конструктора?

Supera i colloqui con l'assistente IA Hintsage

Risposta

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:

  • Se la classe gestisce risorse (ad esempio, ha puntatori grezzi), il costruttore di copia generato automaticamente porterà a errori di doppia liberazione di memoria e perdite di memoria.
  • È necessario assicurarsi che il costruttore di copia copi correttamente le risorse (di solito deep copy).

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; }

Domanda insidiosa

"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); }

Esempi di errori reali causati da mancanza di conoscenza delle sfumature del tema


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.