Llamar a eliminar en la variable asignada en la stack

Ignorando el estilo y el diseño de la progtwigción, ¿es “seguro” llamar a eliminar en una variable asignada en la stack?

Por ejemplo:

int nAmount; delete &nAmount; 

o

 class sample { public: sample(); ~sample() { delete &nAmount;} int nAmount; } 

No , no es seguro llamar a delete en una variable asignada por stack. Solo debe llamar delete en elementos creados por new .

  • Para cada malloc o calloc , debe haber exactamente uno free .
  • Para cada new debería haber exactamente una delete .
  • Para cada new[] debe haber exactamente una delete[] .
  • Para cada asignación de stack, no debe haber liberación o eliminación explícita. El destructor se llama automáticamente, donde corresponda.

En general, no puede mezclar y combinar ninguno de estos, por ejemplo, no free o delete[] -ing un new objeto. Hacerlo da como resultado un comportamiento indefinido.

Bueno, probemos:

 jeremy@jeremy-desktop:~$ echo 'main() { int a; delete &a; }' > test.cpp jeremy@jeremy-desktop:~$ g++ -o test test.cpp jeremy@jeremy-desktop:~$ ./test Segmentation fault 

Entonces aparentemente no es seguro en absoluto.

Tenga en cuenta que cuando asigna un bloque de memoria utilizando new (o malloc para ese caso), el bloque real de memoria asignado será mayor que el que solicitó. El bloque de memoria también contendrá cierta información de contabilidad para que cuando libere el bloque, pueda volver a colocarse fácilmente en el grupo libre y posiblemente combinarse con bloques libres adyacentes.

Cuando intentas liberar cualquier memoria que no hayas recibido de nuevo, esa información de contabilidad no estará allí, pero el sistema actuará como es y los resultados serán impredecibles (generalmente malos).

Sí, es un comportamiento indefinido: pasar para delete cualquier cosa que no venga de new es UB:

Estándar de C ++, sección 3.7.3.2.3: El valor del primer argumento suministrado a una de las funciones de desasignación proporcionadas en la biblioteca estándar puede ser un null puntero null ; si es así, y si la función de desasignación es una proporcionada en la biblioteca estándar, la llamada a la función de desasignación no tiene ningún efecto. De lo contrario, el valor proporcionado al operator delete(void*) en la biblioteca estándar será uno de los valores devueltos por una invocación previa de cualquier operator new(std::size_t) u operator new(std::size_t, const std::nothrow_t&) en la biblioteca estándar.

Las consecuencias del comportamiento indefinido son, bueno, indefinidas. “No pasa nada” es una consecuencia tan válida como cualquier otra cosa. Sin embargo, por lo general, “no ocurre nada de inmediato”: la desasignación de un bloque de memoria no válido puede tener graves consecuencias en llamadas posteriores al asignador.

Después de jugar un poco con g ++ 4.4 en Windows, obtuve resultados muy interesantes:

  1. invocar eliminar en una variable de stack no parece hacer nada. No arrojar errores, pero puedo acceder a la variable sin problemas después de la eliminación.

  2. Tener una clase con un método con delete this elimina con éxito el objeto si está asignado en el montón, pero no si está asignado en la stack (si está en la stack, no pasa nada).

Nadie puede saber lo que sucede. Esto invoca un comportamiento indefinido, por lo que literalmente puede pasar cualquier cosa. No hagas esto

No, la memoria asignada usando new debe eliminarse usando delete operator y la asignada usando malloc debe eliminarse usando free. Y no es necesario desasignar la variable asignada en la stack.

Un ángel pierde sus alas … Solo puedes llamar delete en un puntero asignado con new , de lo contrario obtendrás un comportamiento indefinido.

aquí la memoria se asigna utilizando la stack, por lo que no es necesario eliminarla de forma manual, pero si se ha asignado dinámicamente

como int * a = new int ()

luego debe eliminar y no eliminar a (a a sí mismo es un puntero), ya que la memoria se asigna desde la tienda gratuita.

Usted ya respondió la pregunta usted mismo. delete solo se debe utilizar para punteros obtenidos a través de new . Hacer cualquier otra cosa es un comportamiento simple e indefinido.

Por lo tanto, no hay nada que diga lo que sucede, cualquier cosa, desde el código que funcione bien hasta el borrado de tu disco duro, es un resultado válido al hacer esto. Así que por favor nunca hagas esto .

Es UB porque no debe invocar eliminar en un elemento que no se haya asignado dinámicamente con nuevo. Es así de simple.