C ++ char array [] memory leak [duplicate]

Aug 18 2020

ho creato char arr [] e gli ho assegnato una stringa letterale

char arr[] = "some string";                  // arr occupies 12 chars in memory
std::cout << std::strlen(arr)  << std::endl; // lenght is 11 chars + 1 null-terminator
                                             //arr[11] is '\0'

poi metto null-terminator in 6 elementi

arr[5] = '\0';
std::cout << std::strlen(arr) << std::endl; // lenght is 5 chars  + 1 null-terminator
  1. È una perdita di memoria?
  2. In che modo il compilatore saprà che deve liberare memoria dopo il primo "\ 0"? (quando cancellerà la variabile arr)
  3. È possibile modificare la lunghezza di questa variabile arr e notificare al compilatore quanto dovrebbe liberare quando si elimina la variabile?

Risposte

5 user253751 Aug 18 2020 at 13:03
  1. È una perdita di memoria?

No.

  1. In che modo il compilatore saprà che deve liberare memoria dopo il primo "\ 0"? (quando cancellerà la variabile arr)

La variabile è di 12 caratteri. È come scrivere:

char arr[12] = "some string";

Quindi libererà sempre 12 caratteri. La variabile è un array di 12 caratteri; il fatto che il sesto carattere sia "\ 0" è completamente irrilevante.

A proposito, una volta impostato il sesto carattere su "\ 0", puoi ancora utilizzare tutti e 12 i caratteri, perché è ancora un array di 12 caratteri. Anche quelli dopo "\ 0". Ma non puoi memorizzare 13 caratteri in esso.

  1. È possibile modificare la lunghezza di questa variabile arr e notificare al compilatore quanto dovrebbe liberare quando si elimina la variabile?

No. Non è possibile modificare la dimensione di nessuna variabile.

6 cigien Aug 18 2020 at 13:03

In questo codice:

char arr[] = "some string";

la variabile arrè un array statico con una dimensione fissa. Non è presente alcuna allocazione dinamica della memoria, quindi non è necessario preoccuparsi delle perdite di memoria. Il compilatore si prenderà cura della memoria, indipendentemente da cosa scrivi arr.

2 JoopEggen Aug 18 2020 at 13:07

Per completezza.

Non vi è inoltre alcuna perdita di memoria nella memoria allocata, come in:

char* arr = (char*) malloc(12);
strcpy(arr, "some string");
arr[6] = '\0';
free(arr);

La gestione della memoria passa dalla memoria allocata (12), non dall'utilizzo sottostante (carattere a terminazione nulle *). (Stile C, allo stesso modo C ++)

1 Slava Aug 18 2020 at 13:56

Sembra che tu l'abbia fatto al contrario. La dimensione dell'array in C ++ non può essere modificata, punto. A causa di questo fatto e perché il fatto che se si passa array come puntatore si perdono informazioni sulla dimensione effettiva di quell'array, l' accordo è stato creato per le stringhe in stile C - 0 byte aka \0terminatore nullo trattato come fine dinamica della stringa. Accordo significa che le funzioni che lavorano con stringhe in stile C lo considerano come una terminazione di stringa. Ciò consente di utilizzare array di dimensioni fisse per stringhe di lunghezza diversa e di passare solo un puntatore senza dimensione di memoria effettiva alle funzioni per leggere da esso (ad esempio stampa su schermo). Si noti, quando si passa un array di caratteri a funzioni che scrivono dati in esso, spesso è necessario dirgli qual è la dimensione effettiva dell'array, in modo che la funzione non acceda alla memoria fuori dai limiti poiché quelle funzioni ignorerebbero il terminatore nullo se è già lì.

Questo è tutto, questo accordo avviene su un livello diverso gestito dagli array. Quindi, qualunque dato tu metta in quell'array non influenzerà la sua dimensione dal punto di vista del linguaggio, per il compilatore C ++ hai creato un array a dimensione fissa ci metti alcuni dati e quando la sua durata è arrivata alla fine, il compilatore lo distrugge come un intero array a dimensione fissa. Non importa se ci metti zero byte o no.

VladfromMoscow Aug 18 2020 at 13:16

Si verifica una perdita di memoria quando una memoria è stata allocata dal programmatore utilizzando l'operatore newe non è stata eliminata utilizzando l'operatore deleteo delete [].

In questa dichiarazione

char arr[] = "some string"; 

È la memoria allocata dal compilatore (o dal sistema) per la matrice di caratteri arr che ha la durata della memorizzazione automatica o la durata della memorizzazione statica. Quindi il compilatore (o il sistema) è responsabile di liberare la memoria allocata. L'indirizzo della memoria allocata è noto al compilatore (o al sistema).

Usando questa affermazione

arr[5] = '\0';

non hai riallocato l'array. Hai appena cambiato il suo contenuto in modo più preciso solo di un suo byte.

In che modo il compilatore saprà che deve liberare memoria dopo il primo "\ 0"? (quando cancellerà la variabile arr)

Perché il compilatore (o il sistema) sa come è stato dichiarato l'oggetto del tipo di matrice.

Per l'oggetto sono stati allocati 12 byte.

char arr[] = "some string"; 

È possibile modificare la lunghezza di questa variabile arr e notificare al compilatore quanto dovrebbe liberare quando si elimina la variabile?

Penso che tu intenda la dimensione dell'oggetto. No, non puoi cambiare la dimensione dell'oggetto perché non sei stato tu ad aver allocato la memoria per l'oggetto.

Potresti riallocare l'oggetto se hai usato l'operatore newper allocarlo come per esempio

char *arr = new char[12];

std::strcpy( arr, "some string" );

//...

char *tmp = new char[20];

strcpy( tmp, "another " );
strcat( tmp, arr );

delete [] arr;
arr = tmp;