Pregunta

Ignorando el estilo y el diseño de la programación, ¿es seguro? llamar a eliminar en una variable asignada en la pila?

Por ejemplo:

   int nAmount;
   delete &nAmount;

o

class sample
{
public:
    sample();
    ~sample() { delete &nAmount;}
    int nAmount;
}
¿Fue útil?

Solución

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

  • Para cada malloc o calloc , debe haber exactamente un libre .
  • Para cada new debe haber exactamente una delete .
  • Para cada new [] debe haber exactamente un delete [] .
  • Para cada asignación de pila, no debe haber una liberación o eliminación explícita. El destructor se llama automáticamente, cuando corresponda.

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

Otros consejos

Bueno, probémoslo:

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 usando new (o malloc para el caso), el bloque de memoria real asignado será mayor que lo que solicitó. El bloque de memoria también contendrá información de contabilidad para que, cuando libere el bloque, pueda volver a colocarse fácilmente en el grupo libre y posiblemente fusionarse con bloques libres adyacentes.

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

Sí, es un comportamiento indefinido: pasar a eliminar cualquier cosa que no provenga de new es UB:

  

Estándar 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 valor de puntero null ; si es así, y si la función de desasignación se proporciona 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 a operator delete (void *) en la biblioteca estándar será uno de los valores devueltos por una invocación previa de cualquiera de operator new (std :: size_t) o operador nuevo (std :: size_t, const std :: nothrow_t & amp;) 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, "nada sucede de inmediato": desasignar un bloqueo de memoria no válido puede tener graves consecuencias en las llamadas posteriores al asignador.

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

  1. llamar a delete en una variable de pila no parece hacer nada. No arrojo 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 pila (si está en la pila , no pasa nada).

Nadie puede saber qué pasa. Esto invoca un comportamiento indefinido, por lo que, literalmente, cualquier cosa puede suceder. No hagas esto.

No, La memoria asignada usando new debe eliminarse usando el operador delete y eso asignado usando malloc debería eliminarse usando free. Y no es necesario desasignar la variable que se asigna en la pila.

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

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

me gusta int * a = new int ()

entonces debe eliminar y no eliminar & amp; a (a en sí mismo es un puntero), porque la memoria se asigna desde la tienda libre.

Ya respondiste la pregunta tú mismo. delete solo debe usarse para punteros obtenidos a través de new . Hacer cualquier otra cosa es un comportamiento indefinido simple y llano.

Por lo tanto, realmente no hay forma de decir qué sucede, cualquier cosa, desde que el código funcione bien hasta que se bloquee hasta borrar el disco duro, es un resultado válido de hacerlo. Entonces, por favor, nunca hagas esto .

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

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top