PDA

View Full Version : [C fedora] problemi con la free ()


Lelex82
02-07-2008, 15:08
ho implementato il seguente codice che praticamente è l'eliminazione di un nodo di tipo treenode, da un albero binario di ricerca:
void TREE_DELETE (treenode_ptr *root,treenode_ptr node_del,struct timeval curr_time,struct CTRL_header* ctrl_head,char** buffer,int *buffer_length,Active_func_list_Ptr *active_list_ptr, int *actived_mtrcs,char** packet,int *coll_sock_descrp,int * sent_exps,char **argv)
{
treenode_ptr tmp,tmp2;
tmp= (treenode*) malloc( sizeof(treenode));
tmp->left=NULL;
tmp->right=NULL;
tmp->p=NULL;
if (node_del->left==NULL || node_del->right==NULL) //il nodo da eliminare ha al massimo un figlio (destro o sinistro)
{
tmp=node_del;
}
else //quando il nodo da eliminare ha due figli
{
tmp=TREE_SUCCESSOR (node_del);
}
if (tmp->left!=NULL)
{
tmp2=tmp->left;
}
else
tmp2=tmp->right;
if (tmp2!=NULL)
{
tmp2->p=tmp->p;
}
if (tmp->p==NULL)
{
*root=tmp2;
}
else
{
if (tmp==(tmp->p)->left)
{
(tmp->p)->left=tmp2;
}
else
(tmp->p)->right=tmp2;
}
if (tmp!=node_del) //cioè se il nodo ha 2 figli quindi si è richiamata la funzione TREE_SUCCESSOR
{
node_del->flow_id=tmp->flow_id;
node_del->start_time=tmp->start_time;
node_del->last_update=tmp->last_update;
node_del->metrics_array=tmp->metrics_array;

//* Free memory *
/*if(Delete_Metrics((*active_list_ptr), tmp->metrics_array)==-1)
{printf("FC: Error deleting metrics\n"); exit(-1);}
free(tmp->metrics_array);*/
free((tmp));
nfm++; //numero di flussi morti
//printf("FREE MEMORY SUCCESSOR\n");
CHECK_EXPORTING (&(*root),node_del,curr_time,&(*ctrl_head), &(*buffer), &(*buffer_length), &(*active_list_ptr),&(*actived_mtrcs), &(*packet), &(*coll_sock_descrp),&(*sent_exps),argv);
}
else
{
if(Delete_Metrics((*active_list_ptr), node_del->metrics_array)==-1)
{printf("FC: Error deleting metrics\n"); exit(-1);}
free(node_del->metrics_array);
free((node_del));
nfm++;
//printf("FREE MEMORY NORMALE\n");
}
//return tmp;

}

se decommento la free () relativa a tmp il programma in esecuzione abortisce dandomi il seguente errore "double free or corruption (out)"
vorrei capire che differenza c'è tra il puntatore tmp e il puntatore node_del???
perchè per il secondo non mi da problemi la free ,mentre per il primo si?

DanieleC88
02-07-2008, 15:58
Vuol dire che cerchi di liberare una zona di memoria non allocata: non ho letto il codice perché sono di fretta e non so quindi dirti il perché, ma rivedi ciò che hai scritto. ;)

Lelex82
04-07-2008, 15:04
Daniele trovi 5 minuti? nn riesco proprio a capire il motivo...

DanieleC88
04-07-2008, 17:28
Ma in pratica stai solo eliminando un nodo da un albero binario di ricerca? Perché se è così, la funzione è più complessa del necessario, oltre ad avere dei problemi. Ad esempio, perché l'affermazione "il nodo da eliminare ha al massimo un figlio" sia vera, devi prima controllare la possibilità che il nodo non abbia alcun figlio. Non c'è motivo nemmeno di allocare ed inizializzare la memoria di tmp se poi vi assegni un differente indirizzo in ogni caso. :)

Ti consiglio di usare dei controlli che isolino i diversi casi da controllare (nodo nullo, nodo senza figli, nodo con un figlio, nodo con due figli), il codice si ridurrà molto e ne guadagnerai in chiarezza. Tempo fa avevo scritto questa funzione:
BNode *BSearchTree_DeleteNode(BNode *t)
{
BNode *pTemp = NULL;

/* Nothing to do */
if (t == NULL)
{
return NULL;
}

/* No children */
if ((t->pLeft == NULL) && (t->pRight == NULL))
{
BTree_DeleteNode(t);
return NULL;
}

/* One child */
if ((t->pLeft != NULL) || (t->pRight != NULL))
{
pTemp = ((t->pLeft != NULL) ? t->pLeft : t->pRight);
BTree_DeleteNode(t);
return pTemp;
}

/* Find the in-order successor */
pTemp = t->pLeft;
while (pTemp)
{
pTemp = pTemp->pRight;
}

t->nData = pTemp->nData;
BTree_DeleteNode(pTemp);
return t;
}
(dove BTree_DeleteNode() non fa altro che chiamare una free()) che fa esattamente quello che credo tu voglia fare, ovvero eliminare un particolare nodo all'interno di un albero binario di ricerca; se vuoi, la puoi facilmente riadattare ai tuoi scopi.

ciao ;)

Lelex82
05-07-2008, 10:31
si l'idea di base è l'eliminazione di un nodo da un albero binario di ricerca, con la variante che bisogna fare un controllo se il nodo da eliminare ha due figli e quindi si richiama la funzione SUCCESSOR().
cmq ho risolto, praticamente andavo a deallocare una zona di memoria che successivamente era di nuovo puntata, quindi al nuovo accesso il puntatore nn aveva riferimenti.
grazie cmq dell'aiuto