Excepciones, memoria dinámica y destructores – c++

Pregunta:


Entiendo que si uno implementa una ADT esta debería comportarse como los tipos nativos y ser sus instancias destruidas al terminar su vida útil, pero…

¿Qué pasa si el usuario de la clase declara un raw pointer para usar new con un tipo de esa ADT?

En principio el destructor será invocado, a menos que se lance una excepción y esa memoria que se perdió. ¿Cómo puedo evitarlo?

Seguidamente incluyo un ejemplo que ilustra el problema:

/*
    Implementación "cutre" de una clase para números 
    complejos, el objetivo es que los objetos de esta
    clase puedan usarse como los tipos nativos, lo que 
    se demuestra problemático al usar un raw pointer para
    almacenar un tipo complejo en el heap.

    Code by José Antonio Martínez Escobedo

*/

#include<iostream>
#include<exception>

class Complex {
public:

    Complex(double real = 0, double img = 0) : r(r), i(i){}

    ~Complex()  // el destructor debería ser invocado dos veces...
    {
        std::cout << "Objeto destruido" << std::endl;
    }

private:

    double r, i;
};

int main()
{
    try
    {
        Complex z1;
        Complex* z2 = new Complex{ 6,1 };
        throw (std::exception{ "Trouble" });
        delete z2;  //memory leak!
    }
    catch (const std::exception& e)
    {
    std::cout << "Exception caught: " << e.what();
    }

    return 0;
}

Preguntado por: José Antonio Martínez Escobedo

Paula_plus_plus

Para evitar ese problema que describes se inventaron los ¡punteros inteligentes!

Los punteros inteligentes residen en la cabecera <memory> y dispones del puntero único (std::unique_ptr) el puntero compartido (std::shared_ptr) y el puntero débil (std::weak_ptr), deberás decidir cuál se ajusta a tus necesidades.


Por lo que deduzco de tu código, el puntero único es lo que en tu caso necesitas:

using Complex_ptr = std::unique_ptr<Complex>;

int main()
{
    try
    {
        Complex z1;
        Complex_ptr z2 = std::make_unique<Complex>(6,1);
        throw std::logic_error("Trouble");
    }
    catch (const std::exception& e)
    {
        std::cout << "Exception caught: " << e.what();
    }

    return 0;
}

Al lanzarse una excepción, el estándar de C++ garantiza que se llamarán los destructores de los objetos del ámbito en que la excepción fue lanzada, así pues z2 es destruido al salir del bloque try.

Si te das cuenta, también he eliminado la instrucción delete z2; ya que el borrado del objeto se hace automáticamente al abandonar el ámbito.

Otras cosas a tener en cuenta.

El constructor de Complex inicializa mal las variables miembro, revísalo:

Complex(double real = 0, double img = 0) : r(real), i(img){}
//                                           ~~~~     ~~~

No se pueden construir excepciones con inicialización de agregado, por otro lado, es mejor lanzar una excepción específica que una genérica, por eso he cambiado tu excepción a esto:

throw std::logic_error("Trouble");

Supongo que tu clase Complex es sólo un ejemplo, pero ten en cuenta que no te hace falta desarrollarla porque C++ dispone de una clase std::complex.

Fuente

Related Posts:

Declarar un array de structs de tamaño dinamico – c++
Pregunta: buenas, lo que quiero conseguir es declarar un struct con array que tenga su tamaño dinamico, pero cuando lo hago el programa se me ...
Problemas con el registro de un archivo .tlb – c# windows vb6
Pregunta: La situación es la siguiente: He creado un pequeño proyecto de librería de clases en C# que me permita realizar ciertas operaciones. El nombre del ...
Uso de js y c# en unity. ¿Igual rendimiento? – javascript c# unity3d
Pregunta: Estoy comenzando con unity . Y veo que se pueden usar c# y js para programar. Mi pregunta es si tanto c# como js ...
Cómo puedo incluir librería beecrypt en un proyecto en C – c
Pregunta: Tengo un archivo .lib (librería) y quiero usarla en un proyecto de C. Para ser más especifica estoy intentando instalar beecrypt que es una librería ...
Ocultar y Mostrar con Mapa de Google – javascript c# asp.net
Pregunta: Tengo un div en mi página ASP.NET que contiene un Mapa de Google, y necesito mostrarlo y ocultarlo pero no me funciona. Este es el ...
para que sirve #ifdef_MSDOS_ en c++? – c++
Pregunta: He tenido problemas porque donde trabajo usan una versión de dev c++ 4.9 y yo uso en mi hogar la 5.1, ...
¿Como instalar C# en SublimeText? – c# sublimetext3 sublimetext
Pregunta: El problema es que actualmente quiero programar sobre esta tecnologia, pero no quiero descargar aun el visual studio porque consume recursos y es bastante ...
Thread en c++ error compilacion – c++
Pregunta: Estoy empezando con threads y he estado siguien varios tutos y creo que esta todo bien, pero a la hora de ejecutarlo me da ...
¿Es posible capturar un segfault con try/catch? – c++ try-catch
Pregunta: Para comprobar si es posible hice lo siguiente: try { int *x = 0; *x = 1234; } catch(...) { ...
Conexion C# con PostgreSQL mediante proveedor Npgsql – c# postgresql
Pregunta: Hola el problema es que la conexión esta bien solo cuando estoy utilizando el ODBC, pero cuando lo cambio al proveedor de PostgreSQL Npgsql, ...
Construcción extraña: objeto = funcion1() && funcion2() ¿Posible? – c#
Pregunta: acabo de encontrarme en una documentación una construcción como esta: var pose = Body.LeftHand.Near(Body.Head) && Body.LeftArm.Bended(90); posees una objeto que debe crearse a partir de la ...
Cómo importar datos de un Excel a DataGrid pero iniciarlo en la segunda fila? – c# sql-server postgresql
Pregunta: Disculpen una duda, como cargar de excel un formato iniciando en la segunda fila? tengo este código solamente que el excel esta justificado en ...
No completa el ciclo foreach – c#
Pregunta: Estoy haciendo un método para invertir palabras que contengan 5 o mas letras. El problema que tengo es que si mi cadena tiene mas ...
Obtener elementos específicos de un array – c array optimización
Pregunta: Buenas, si yo por ejemplo hago: char buf; fgets(buf, 1024, stdin); ¿Puedo coger los caracteres que escribí del array sin coger los elementos que no utilicé? ¿O ...
Averiguar número de elementos en un array de LUA – c++ array lua
Pregunta: ¿Cómo puedo averiguar el número de elementos que contiene un array en un fichero LUA? me gustaría poder volcarlo a un entero desde C++. -- ...
Tags:

Add a Comment

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *