PDA

View Full Version : code in C


bizzu
20-09-2003, 20:12
Sto facendo un programma in C che fa uso delle code. Questo è la definizione degli oggetti della coda:
typedef struct lista {
int ind;
int tipo;
struct lista *next;
}
Quando devo estrarre un oggetto dalla testa della coda, lo "copio" in una struttura temporanea, poi sposto il puntatore alla testa e lo cancello. Così:
k.ind = testa->ind;
k.tipo = testa->tipo;
corrente = testa;
testa = testa->next;
free(corrente);
Quando faccio questa operazione il MS Visual C++ mi dà un errore strano a runtime, che ho allegato. Se clicco Retry e poi debug (nella finestra classica d'errore di windows, dà un errore nel file vc98\crt\src\dbgheap.c. Il messaggio esatto è "User breakpoint called from code at 0x403adf".
Sono certo che è il free() che dà l'errore, perché se lo tolgo fila tutto liscio. Cosa può essere? :cry:
Help!

mjordan
20-09-2003, 20:49
Originariamente inviato da bizzu
Sto facendo un programma in C che fa uso delle code. Questo è la definizione degli oggetti della coda:
typedef struct lista {
int ind;
int tipo;
struct lista *next;
}
Quando devo estrarre un oggetto dalla testa della coda, lo "copio" in una struttura temporanea, poi sposto il puntatore alla testa e lo cancello. Così:
k.ind = testa->ind;
k.tipo = testa->tipo;
corrente = testa;
testa = testa->next;
free(corrente);
Quando faccio questa operazione il MS Visual C++ mi dà un errore strano a runtime, che ho allegato. Se clicco Retry e poi debug (nella finestra classica d'errore di windows, dà un errore nel file vc98\crt\src\dbgheap.c. Il messaggio esatto è "User breakpoint called from code at 0x403adf".
Sono certo che è il free() che dà l'errore, perché se lo tolgo fila tutto liscio. Cosa può essere? :cry:
Help!

Dovresti essere un pochino + preciso. Per esempio corrente in quel punto è una struttura o un puntatore a struttura? La cosa è diversa. Infatti free() può essere utilizzata solo per deallocare memoria allocata con funzioni della famiglia malloc(), non per distruggere variabili. E una struttura è considerata una variabile.
Pertanto se 'corrente' è una variabile struttura creata con una definizione di variabile, non puoi usare la free(). Questo potrebbe spiegare il fantomatico errore "DAMAGE" che ti restituisce Visual C++. Difatti molto probabilmente la free() in quel punto starà deallocando chissà cosa ...

recoil
21-09-2003, 10:36
w il garbage collector :p :D

probabilmente stai cercando di liberare un indirizzo di memoria che non è nello heap, avrai fatto qualche casino con i puntatori e con le variabili.

bizzu
21-09-2003, 15:38
corrente è un puntatore a struttura; non ho usato la malloc con "corrente", ma con "nuovo" che è sempre un puntatore a struttura che uso quando devo inserire gli elementi della coda. Pensavo che facendo puntare a corrente una struttura precedentemente allocata, potessi liberarla semplicemente con free().
Come posso fare allora per deallocare la memoria degli elementi estratti? Non vorrei lasciarla occupata, e siccome il garbage collector non ce l'ho :p ...

verloc
21-09-2003, 16:20
Io pensavo che ti avessero costretto con la pistola a farti la coda in C :)

Usa la STL che ti da la coda bella e che fatta(e più efficiente di quanto tu mai possa fare ...senza offesa)

Oh ma la STL non la usa mai nessuno? (eppure ti allunga la vita...) :eek:

mjordan
21-09-2003, 16:52
Originariamente inviato da verloc
Usa la STL che ti da la coda bella e che fatta(e più efficiente di quanto tu mai possa fare ...senza offesa)

Oh ma la STL non la usa mai nessuno? (eppure ti allunga la vita...) :eek:

Ingegnere, stiamo usando il C, non il C++ :rolleyes:

mjordan
21-09-2003, 16:57
Originariamente inviato da bizzu
Pensavo che facendo puntare a corrente una struttura precedentemente allocata, potessi liberarla semplicemente con free().


Pensi bene. free() prende un indirizzo di memoria dal quale comincia a deallocare memoria. Quello che ti dicevo io è semplicemente che la memoria dev'essere stata allocata con malloc(), non importa poi se il puntatore che passi è quello "originale" o una copia. Il valore è uguale in entrambi i casi.


Come posso fare allora per deallocare la memoria degli elementi estratti? Non vorrei lasciarla occupata, e siccome il garbage collector non ce l'ho :p ...

Evidentemente non ci sono sufficienti informazioni per poter stabilire un eventuale errore.

verloc
22-09-2003, 07:47
Originariamente inviato da mjordan
Ingegnere, stiamo usando il C, non il C++ :rolleyes:

Eddai...non ti innervosire. :)

Sai quante volte qualcuno si incarta perchè non sa dell'esistenza dei containers STL?

Se è per imparare gli algoritmi ...va bene.Altrimenti...
"Thinking in C++" :)

mjordan
22-09-2003, 21:51
E chi si innervosisce :D
Volevo solo dire che siamo in un contesto C e la programmazione di una struttura di dati non è un motivo per cambiare linguaggio :D

LukeHack
23-09-2003, 04:06
Originariamente inviato da mjordan
Dovresti essere un pochino + preciso. Per esempio corrente in quel punto è una struttura o un puntatore a struttura? La cosa è diversa. Infatti free() può essere utilizzata solo per deallocare memoria allocata con funzioni della famiglia malloc(), non per distruggere variabili. E una struttura è considerata una variabile.
Pertanto se 'corrente' è una variabile struttura creata con una definizione di variabile, non puoi usare la free(). Questo potrebbe spiegare il fantomatico errore "DAMAGE" che ti restituisce Visual C++. Difatti molto probabilmente la free() in quel punto starà deallocando chissà cosa ...

è sicuramente un puntatore a lista (lista* corrente )
poichè se non lo fosse allora il compilatore darebbe errore A PRESCINDERE dal free, difatti compare un'assegnazione (corrente = testa) dove testa è sicuramente un lista* (puntatore)...
con queste poche info cmq l'unico consiglio che mi viene in mente è di mettere due printf prima dell'invocazione del free, così da leggere i valori di corrente e valutarne la consistenza (quindi un debug:D )
ciao!

mjordan
23-09-2003, 05:53
Originariamente inviato da LukeHack
è sicuramente un puntatore a lista (lista* corrente )
poichè se non lo fosse allora il compilatore darebbe errore A PRESCINDERE dal free, difatti compare un'assegnazione (corrente = testa) dove testa è sicuramente un lista* (puntatore)...
con queste poche info cmq l'unico consiglio che mi viene in mente è di mettere due printf prima dell'invocazione del free, così da leggere i valori di corrente e valutarne la consistenza (quindi un debug:D )
ciao!

Chè c'entra scusa. Quell'assegnazione la puoi interpretare diversamente a seconda del contesto (contesto che non è chiaro). Se sono puntatori l'assegnamento riguarda indirizzi, se sono strutture l'assegnamento riguarda i campi della struttura. Pertanto non ci sarebbe quell'errore che stai citando tu.

LukeHack
23-09-2003, 13:35
k.ind = testa->ind;
k.tipo = testa->tipo;
corrente = testa;

testa è un puntatore, non può essere uno struct sennò l'operatore "->" darebbe errore a prescindere dal free:) ergo, corrente è un puntatore:) :oink:

cmq, al creatore del thread, hai fatto un debug? hai ulteriori info al riguardo?

bizzu
24-09-2003, 13:39
Innanzitutto grazie a tutti per l'aiuto.

Il debug l'ho fatto, ma non ha risolto niente. Mi spiego: il programma funziona perfettamente, non ci sono inconsistenze in quanto tutti gli elementi della lista vengono letti correttamente, e next punta effettivamente al successivo elemento della lista. Facendo il debug, arrivato al famigerato "free(corrente)" (che per fugare eventuali dubbi è un puntatore e non una struttura) dà lo stesso errore che dà a runtime. Se lo tolgo, funziona tutto perfettamente (tranne per il fatto che quella piccola parte di memoria rimane allocata fino al termine del programma).

Aggiungo un altro dettaglio che magari potrebbe aiutarci (o incasinare ancora di più le cose!): quel problema con free lo fa solo all'interno delle funzioni, se faccio dei free (sugli stessi tipi di strutture) nel main(), non c'è nessun errore.

LukeHack
24-09-2003, 13:45
ok allora prova a passare i riferimenti alle strutture e non i puntatori,come parametri delle funzioni!
il vc++ gestisce talvolta male,te lo dico per esperienza, lo sharing di bytes tra puntatori, facendo come ti dico io gli passi direttamente l'indirizzo e quindi non hai sharing...
famme sape:)

bizzu
24-09-2003, 15:43
Originariamente inviato da LukeHack
ok allora prova a passare i riferimenti alle strutture e non i puntatori,come parametri delle funzioni!
il vc++ gestisce talvolta male,te lo dico per esperienza, lo sharing di bytes tra puntatori, facendo come ti dico io gli passi direttamente l'indirizzo e quindi non hai sharing...
famme sape:)

I puntatori usati nella funzione non sono passati come parametro, ma dichiarati nel corpo della funzione, perché vengono usati solo al suo interno e poi non servono +.

LukeHack
24-09-2003, 19:52
scusa posta il codice gli dò un'occhiata

bizzu
24-09-2003, 23:14
Eccolo; guarda nella funzione CamminoAumentante alla riga 55 e in quella Ricostruisci alla riga 188, ci sono i free incriminati. Nella prima funzione ho usato una coda, nella seconda una pila.
(bisogna togliere il .zip, visto che vBulletin rompe con le estensioni :rolleyes: )

LukeHack
25-09-2003, 00:39
caro bizzu,mi spiace ma il codi che m'hai mandato è formalmente corretto, ossia a rigor di logica dovrebbe funzionare...MA....
non è cosi..
il problema è la struttura dell'algoritmo, l'uso dei puntatori è una delle cose più delicate in c e tu non li usi,ne abUsi:rolleyes:
infatti non puoi fare un free di una struttura PER OGNI ciclo do while, il free lo devi maneggiare con cura e fare in modo che,qualora ti servono record d'appoggio per scrivere i dati
(nel tuo caso la var "corrente") questa NON deve essere deallocata e riallocata continuamente...il motivo è questo:

supponi che a testa inizialmente sia dato il valore 0x00320ff
(ho fatto un profondo debug:D ), ciò che succede dopo è che corrente viene freeato,dopo che gli è stato assegnato il valore di testa (qui cìè pure un brutto errore,deallochi e poi usi gli indirizzi..)
riga 56 o 57)...
e, dentro al ciclo fai una malloc a "nuovo" che assume il valore appena freeato (tipico comportamento)...ma questo indirizzo E' STATO GIA' DEALLOCATO DAL compilatore quindi, al ciclo successivo, nel RIFARE IL FREE SU CORRENTE (che ha sempre il valore di testa) L'ERRORE...stai deallocando un indirizzo GIA' DEALLOCATO!

so che è lunga come spiegazione ma puoi credermi, l'errore di per sè sta nell'algoritmo che,perdonami, è un pò troppo "javistico"
:D e fantasioso:O

PROVARE (il debug, ma serio stavolta) PER CREDERE!
ciao

bizzu
25-09-2003, 21:46
Grazie mille LukeHack... neanche il professore avrebbe debuggato il programma così a fondo!:p
Ho capito l'errore che ho fatto, adesso mi scervello un po' per rimettere a posto quelle listacce.
L'algoritmo è effettivamente "fantasioso" (ho fatto una bella fatica a ricavarlo da quello spiegato "a parole"), cmq è abbastanza efficiente e ha dei buoni tempi di esecuzione su matrici grandi.

Cmq non pensavo che i puntatori fossero così suscettibili :D
Io li liberavo con free e pensavo che puntando NULL tornassero come nuovi!:sofico: eheh
Grazie ancora
ciao

LukeHack
26-09-2003, 01:00
ma figurati:D fammi sapere come risolvi:ubriachi: