C ++ char array [] pérdida de memoria [duplicado]

Aug 18 2020

Creé char arr [] y le asigné una cadena literal

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'

a continuación, pongo un terminador nulo en el elemento 6

arr[5] = '\0';
std::cout << std::strlen(arr) << std::endl; // lenght is 5 chars  + 1 null-terminator
  1. ¿Es una pérdida de memoria?
  2. ¿Cómo sabrá el compilador que debe liberar memoria después del primer '\ 0'? (cuando borrará la variable arr)
  3. ¿Es posible cambiar la longitud de esta variable arr y notificar al compilador cuánto debería liberar al eliminar la variable?

Respuestas

5 user253751 Aug 18 2020 at 13:03
  1. ¿Es una pérdida de memoria?

No.

  1. ¿Cómo sabrá el compilador que debe liberar memoria después del primer '\ 0'? (cuando borrará la variable arr)

La variable es de 12 caracteres. Es lo mismo que escribir:

char arr[12] = "some string";

Así que siempre liberará 12 caracteres. La variable es una matriz de 12 caracteres; el hecho de que el sexto carácter sea '\ 0' es completamente irrelevante.

Por cierto, una vez que haya configurado el sexto carácter en '\ 0', aún puede usar los 12 caracteres, porque sigue siendo una matriz de 12 caracteres. Incluso los que siguen al '\ 0'. Pero no puedes almacenar 13 caracteres en él.

  1. ¿Es posible cambiar la longitud de esta variable arr y notificar al compilador cuánto debería liberar al eliminar la variable?

No. No es posible cambiar el tamaño de ninguna variable.

6 cigien Aug 18 2020 at 13:03

En este código:

char arr[] = "some string";

la variable arres una matriz estática con un tamaño fijo. Aquí no hay asignación de memoria dinámica, por lo que no hay necesidad de preocuparse por las pérdidas de memoria. El compilador se ocupará de la memoria, independientemente de lo que escriba arr.

2 JoopEggen Aug 18 2020 at 13:07

Por completitud.

Tampoco hay pérdida de memoria en la memoria asignada, como en:

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

La gestión de la memoria se basa en la memoria asignada (12), no en el uso subyacente (char * terminado en nulo). (Estilo C, C ++ igualmente)

1 Slava Aug 18 2020 at 13:56

Parece que lo entendiste al revés. El tamaño de la matriz en C ++ no se puede cambiar, punto. Debido a ese hecho y al hecho de que si pasa la matriz como un puntero, pierde información del tamaño real de esa matriz, el acuerdo se creó para cadenas de estilo C: 0 bytes, también \0conocido como terminador nulo, tratado como final dinámico de la cadena. Acuerdo significa que las funciones que trabajan con cadenas de estilo C lo tratan como una terminación de cadena. Eso le permite usar una matriz de tamaño fijo para cadenas de diferente longitud y pasar solo un puntero sin el tamaño de la memoria real a funciones para leer de él (por ejemplo, imprimir en pantalla). Tenga en cuenta que cuando pasa una matriz de caracteres a funciones que escriben datos en ella, a menudo necesita decirle cuál es el tamaño real de la matriz, para que la función no acceda a la memoria fuera de los límites, ya que esas funciones ignorarían el terminador nulo si ya está allí.

Eso es todo, este acuerdo ocurre en diferentes capas que administraron los arreglos. Entonces, cualquier dato que coloque en esa matriz no afectará su tamaño desde el punto de vista del lenguaje, para el compilador de C ++ que creó una matriz de tamaño fijo , colocó algunos datos en ella y cuando su vida útil llegó al final, el compilador la destruye como una matriz completa de tamaño fijo. No le importa si puso cero bytes allí o no.

VladfromMoscow Aug 18 2020 at 13:16

Una pérdida de memoria ocurre cuando el programador asignó una memoria usando el operador newy no fue eliminada usando el operador deleteo delete [].

En esta declaración

char arr[] = "some string"; 

Es el compilador (o el sistema) la memoria asignada para el arreglo de caracteres arr que tiene la duración del almacenamiento automático o la duración del almacenamiento estático. Entonces el compilador (o el sistema) es responsable de liberar la memoria asignada. El compilador (o el sistema) conoce la dirección de la memoria asignada.

Usando esta declaración

arr[5] = '\0';

no reasignó la matriz. Acaba de cambiar su contenido de manera más precisa solo un byte.

¿Cómo sabrá el compilador que debe liberar memoria después del primer '\ 0'? (cuando borrará la variable arr)

Porque el compilador (o sistema) sabe cómo se declaró el objeto del tipo de matriz.

Para el objeto se asignaron 12 bytes.

char arr[] = "some string"; 

¿Es posible cambiar la longitud de esta variable arr y notificar al compilador cuánto debería liberar al eliminar la variable?

Creo que te refieres al tamaño del objeto. No, no puede cambiar el tamaño del objeto porque no fue usted quien asignó la memoria para el objeto.

Podría reasignar el objeto si utilizó el operador newpara asignarlo como, por ejemplo,

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;