es.davy.ai

Preguntas y respuestas de programación confiables

¿Tienes una pregunta?

Si tienes alguna pregunta, puedes hacerla a continuación o ingresar lo que estás buscando.

free(): puntero inválido cuando se utiliza get() en lugar de release() en unique_ptr

Tengo el siguiente programa:

#include <list>
#include <stack>  
#include <memory>

struct ChildNode {};

struct value_node_ptr : public std::unique_ptr<childnode> {
    using std::unique_ptr<childnode>::unique_ptr;
    using std::unique_ptr<childnode>::reset;
};

struct Node {
    std::list<value_node_ptr> children;
    void addChild(ChildNode* child){
        children.emplace_back(child);
    }
};

void iterateChildren(Node* node){
    for(auto it=node->children.begin(); it != node->children.end(); ++it){
        auto child = it->release();
        //do stuff with child
    }
}

int main() {
    ChildNode child;
    Node node;
    node.addChild(&child);

    std::stack<node*> nodes;
    nodes.push(&node);
    iterateChildren(nodes.top());

    nodes.pop();
}

Esto funciona bien. Pero si uso it->get() en lugar de it->release() en la función iterateChildren, obtengo el error:

free(): invalid pointer

Quiero reutilizar los hijos en algún momento y pensé que it->release() destruiría el puntero para que no sea utilizable después, pero parece que el puntero sigue ahí, lo cual me confunde.

Además, pensé que it->get() era la opción correcta ya que solo quiero obtener el valor y no destruir el puntero. Estaba pensando que podría haber algún error de fuga de memoria al llamar a it->get(), por lo que intenté llamar a it->reset() en cada uno de los hijos después de haber terminado de usarlos, pero esto tampoco resolvió el error.

¿Alguien puede explicarme este comportamiento y qué método debo usar?</node*>

Tags:  , ,

Answer

  1. Avatar for davy.ai

    La razón por la cual el uso de it->get() causa el error es que devuelve un puntero sin procesar al objeto propiedad del unique_ptr. El unique_ptr sigue siendo el propietario del objeto y lo eliminará cuando quede fuera del ámbito. Sin embargo, estás accediendo al objeto a través de un puntero sin procesar después de que ya haya sido eliminado, lo que resulta en un comportamiento indefinido y, en este caso, un error “free(): invalid pointer”.

    Por otro lado, it->release() transfiere la propiedad del objeto a ti, dejando el unique_ptr en un estado nulo. Esto significa que tú asumes la responsabilidad de eliminar el objeto y puedes accederlo de forma segura a través del puntero sin procesar. Por eso, el código funciona cuando se utiliza it->release() en lugar de it->get().

    Si deseas reutilizar los hijos más tarde, puedes retener los punteros sin procesar y crear un mecanismo para eliminarlos cuando hayas terminado con ellos. Alternativamente, puedes envolver los punteros sin procesar en otro puntero inteligente como shared_ptr o weak_ptr, que se encargarán de la propiedad de los objetos.

    Usar it->reset() después de usar el puntero sin procesar obtenido de it->get() no resolverá el error porque reset() también elimina el objeto propiedad del unique_ptr, dejándote con un puntero nulo. Esto significa que tendrá el mismo efecto que usar it->release() pero sin transferir la propiedad.

    Por lo tanto, en este caso, es apropiado utilizar it->release() para transferir la propiedad del objeto a ti, de manera que puedas acceder al objeto de forma segura sin obtener ningún error.

Comments are closed.