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.

Cómo eliminar un puntero almacenado dentro de un nodo?

Estoy tratando de configurar un árbol binario compuesto por nodos que contienen punteros a objetos, pero en mi función “limpiar árbol” encuentro una violación de acceso de lectura cuando intento liberar memoria en el puntero dentro del nodo. ¿Por qué no se produce una excepción cuando libero memoria en el puntero raíz, pero sí ocurre en el puntero int dentro del nodo?

Se produjo una excepción: violación de acceso de lectura. Era 0x2.

“`
class Tree {
private:
struct Node {
int* val = nullptr;
Node* right = nullptr;
Node* left = nullptr;
};
Node* root = nullptr;

public:
bool Insert(int* num);
void Empty();
bool isEmpty() const;
};

void Tree::Empty()
{
while (!(root == nullptr)) // Simplemente estoy manejando el caso más simple por ahora
{
if (root->left == nullptr && root->right == nullptr)
{
delete root->val; // Violación de acceso de lectura
delete root;
root = nullptr;
break;
}

    [...]
}

}

bool Tree::Insert(int* num)
{
Node* insertion = new Node;
int* temp = new int(*num);
insertion->val = temp;

if (root == nullptr)
{
    root = insertion;
    return true;
}

Node* c_node = root;

while (true)
{
    if (*temp == *c_node->val)
    {
        delete temp;
        delete insertion;
        return false;
    }

    if (*temp > *c_node->val)
    {
        if (c_node->right != nullptr)
        {
            c_node = c_node->right;
            continue;
        }

        c_node->right = insertion;
        return true;
    }

    if (c_node->left != nullptr)
    {
        c_node = c_node->left;
        continue;
    }

    c_node->left = insertion;
    return true;
}

}

int main()
{
int a = 2;

Tree my_tree;
my_tree.Insert(&a);
my_tree.Empty();

}

Agradecería cualquier comentario.

Tags:  , ,

Answer

  1. Avatar for davy.ai

    La razón por la cual no se arroja ninguna excepción al liberar la memoria en el puntero raíz es que el propio puntero raíz no apunta a una memoria asignada, sino que es simplemente un puntero a un objeto Node asignado en la pila por quien llama al constructor de la clase Tree.

    Por otro lado, el puntero int dentro del objeto Node apunta a una memoria asignada dinámicamente, la cual debe ser liberada antes de que el propio objeto Node sea destruido. Cuando intentas liberar la memoria apuntada por val, se produce una violación de acceso de lectura porque la memoria ya ha sido liberada en la función Insert. En otras palabras, cuando eliminas temp en la función Insert, estás eliminando la misma memoria a la que apunta val más adelante en la función Empty.

    Para solucionar este problema, debes asegurarte de que solo eliminas la memoria que ha sido asignada dinámicamente y no apuntas a ninguna memoria que ya haya sido liberada. Una forma de hacer esto es establecer el puntero val de cada objeto Node en nullptr después de eliminar su memoria en la función Empty. Por ejemplo:

    if (root->left == nullptr && root->right == nullptr)
    {
        delete root->val;
        root->val = nullptr;
        delete root;
        root = nullptr;
        break;
    }
    

    Al establecer val en nullptr después de eliminar la memoria, te aseguras de que no se pueda acceder a ella más tarde en la función, evitando cualquier violación de acceso de lectura.

Comments are closed.