¿Cómo se elimina “saber” el tamaño de la matriz de operandos?

Foo* set = new Foo[100]; // ... delete [] set; 

No pasa los límites de la matriz para delete[] . Pero, ¿dónde se almacena esa información? ¿Está estandarizado?

Cuando asigna memoria en el montón, su asignador hará un seguimiento de cuánta memoria ha asignado. Esto generalmente se almacena en un segmento de “cabeza” justo antes de la memoria que se asigna. De esta manera, cuando es hora de liberar la memoria, el desasignador sabe exactamente cuánta memoria liberar.

Uno de los enfoques para los comstackdores es asignar un poco más de memoria y almacenar un recuento de elementos en un elemento principal.

Ejemplo de cómo se podría hacer:

aquí

 int* i = new int[4]; 

el comstackdor asignará sizeof(int)*5 bytes.

 int *temp = malloc(sizeof(int)*5) 

Almacenará “4” en el primer sizeof(int) bytes sizeof(int)

 *temp = 4; 

y establecer i

 i = temp + 1; 

Entonces i una matriz de 4 elementos, no 5.

Y eliminación

 delete[] i; 

se procesará de la siguiente manera:

 int *temp = i - 1; int numbers_of_element = *temp; // = 4 ... call destructor for numbers_of_element elements ... that are stored in temp + 1, temp + 2, ... temp + 4 if needed free (temp) 

La información no está estandarizada. Sin embargo, en las plataformas en las que he trabajado, esta información se almacena en la memoria justo antes del primer elemento. Por lo tanto, en teoría, podría acceder e inspeccionarlo, sin embargo, no vale la pena.

También esta es la razón por la que debe usar delete [] cuando asigna memoria con new [], ya que la versión de matriz de delete sabe que (y dónde) necesita buscar para liberar la cantidad correcta de memoria y llama al número apropiado de destructores para los objetos.

Básicamente está organizado en memoria como:

[info] [mem que pediste …]

Donde la información es la estructura utilizada por su comstackdor para almacenar la cantidad de memoria asignada, y lo que no.

Sin embargo, esto depende de la implementación.

Esto no es algo que está en la especificación, depende de la implementación.

Porque la matriz que se ‘eliminará’ debería haberse creado con un único uso del operador ‘nuevo’. La ‘nueva’ operación debería haber puesto esa información en el montón. De lo contrario, ¿cómo podrían los usos adicionales de los nuevos saber dónde termina el montón?

Se define en el estándar de C ++ como específico del comstackdor. Lo que significa magia de comstackdor. Puede romper con restricciones de alineación no triviales en al menos una plataforma principal.

Puede pensar en posibles implementaciones al darse cuenta de que delete[] solo está definido para los punteros devueltos por new[] , que puede no ser el mismo puntero que devuelve el operator new[] . Una implementación en la naturaleza es almacenar el recuento de la matriz en la primera int devuelto por el operator new[] , y tener new[] devolver una desviación del puntero más allá de eso. (Esta es la razón por la cual las alineaciones no triviales pueden romperse new[] ).

Tenga en cuenta que el operator new[]/operator delete[] ! = new[]/delete[] .

Además, esto es ortogonal a cómo C conoce el tamaño de la memoria asignada por malloc .

No está estandarizado. En el tiempo de ejecución de Microsoft, el nuevo operador usa malloc () y el operador de eliminación usa free (). Entonces, en esta configuración, su pregunta es equivalente a lo siguiente: ¿Cómo sabe free () el tamaño del bloque?

Existe cierta contabilidad detrás de las escenas, es decir, en el tiempo de ejecución de C.

Este es un problema más interesante de lo que podrías pensar al principio. Esta respuesta es sobre una posible implementación.

En primer lugar, mientras que en algún nivel su sistema tiene que saber cómo ‘liberar’ el bloque de memoria, el malloc / free subyacente (que new / delete / new [] / delete [] generalmente llama) no siempre recuerda exactamente cuánta memoria usted lo solicita, puede redondearse (por ejemplo, una vez que está por encima de 4K, a menudo se redondea al siguiente bloque del tamaño de 4K).

Por lo tanto, incluso si pudiéramos obtener el tamaño del bloque de memoria, eso no nos dice cuántos valores hay en la nueva memoria ed, ya que puede ser más pequeño. Por lo tanto, tenemos que almacenar un número entero adicional que nos diga cuántos valores hay.

EXCEPTO, si el tipo que se está construyendo no tiene un destructor, entonces delete [] no tiene que hacer nada excepto liberar el bloque de memoria, ¡y por lo tanto no tiene que almacenar nada!