Precedente :: Successivo |
Autore |
Messaggio |
saetta Eroe in grazia degli dei

Registrato: 25/02/08 11:52 Messaggi: 129
|
Inviato: 25 Set 2008 09:44 Oggetto: [c] free() ... |
|
|
Buondì, intanto...
Ho un dubbio...
Se ho un vettore di struct, allocato con calloc, e volessi eliminare un elemento va bene questo algoritmo?
(elem è puntatore alla struct)
remove(...)
{
elem = cerca_elemento da eliminare();
se lo trovi
prev_element = elem -1;
sposta con memcpy()tutti gli elementi che seguivano elem di 1 posizione indietro(incremento: prev = elem; elem=elem+1; )
free(elem) //che qui punta all'ultimo elemento dell'array, ormai doppione del penultimo
}
Insomma, mi chiedevo se, trattandosi di un vettore, è possibile deallocare solo l'ultima cella oppure se la free deve coinvolgere tutta l'area allocata da calloc (ovvero tutto il vettore) |
|
Top |
|
 |
SverX Supervisor Macchinisti


Registrato: 25/03/02 12:16 Messaggi: 11809 Residenza: Tokelau
|
Inviato: 25 Set 2008 12:52 Oggetto: Re: [c] free() ... |
|
|
approccio curioso un vettore di struct...
a parte il parere personale, se la lunghezza del vettore cambia dinamicamente già vuol dire che probabilmente il vettore non era una buona soluzione, forse meglio optare per una lista.
Se invece non puoi fare altrimenti (facciamo finta... per motivi didattici ad esempio) allora penso che la cosa migliore sia aggiungere un flag booleano 'cancellato' alla tua struct e quando farai una cancellazione di un elemento NON ti metterai a ricopiare tutti i successivi e poi a ridimensionare l'array, sono operazioni molto dispendiose in termini di performance, ma semplicemente cambierai lo stato del flag.
 |
|
Top |
|
 |
saetta Eroe in grazia degli dei

Registrato: 25/02/08 11:52 Messaggi: 129
|
Inviato: 25 Set 2008 13:49 Oggetto: |
|
|
in realtà la dimensione non dovrebbe cambiare... ma sai, volevo dare la possibilità di farlo (per casi estremi) a chi volesse modificare il mio sorgente. (di certo non mi metterò ad implementarli io...)
Non avevo mai usato un vettore di struct, ma sempre vett di puntatori a struct,e devo dire... che facevo bene.
Il flag cel'ho già, può rappresentare ben 3 stati: attivo, disattivo per tot tempo e disattivo per sempre(che comunque può essere modificato, serve a me per non considerarlo in certe occasioni)
lunica cosa che mi rimane dubbia è:
le struct dentro il vettore hanno un campo char* che viene allocato a suo tempo.
Nel liberare il vettore cercavo di fare prima una free su tutti questi char*, poi sul vettore stesso. Mi da seg.fault nella free().
Se faccio solo la free() sul vettore mica libero anche le stringhe corrispondenti ad ogni struct !!!
Che posso fare? |
|
Top |
|
 |
saetta Eroe in grazia degli dei

Registrato: 25/02/08 11:52 Messaggi: 129
|
Inviato: 25 Set 2008 14:16 Oggetto: |
|
|
[RISOLTO]
ho sostituito il while per rimuovere le stringhe con un for... e la magia è fatta.
Grazie!  |
|
Top |
|
 |
chemicalbit Dio maturo


Registrato: 01/04/05 18:59 Messaggi: 18597 Residenza: Milano
|
Inviato: 25 Set 2008 20:58 Oggetto: Re: [c] free() ... |
|
|
SverX ha scritto: | se la lunghezza del vettore cambia dinamicamente già vuol dire che probabilmente il vettore non era una buona soluzione, forse meglio optare per una lista. | Cioé, come? |
|
Top |
|
 |
SverX Supervisor Macchinisti


Registrato: 25/03/02 12:16 Messaggi: 11809 Residenza: Tokelau
|
Inviato: 26 Set 2008 11:54 Oggetto: Re: [c] free() ... |
|
|
chemicalbit ha scritto: | SverX ha scritto: | se la lunghezza del vettore cambia dinamicamente già vuol dire che probabilmente il vettore non era una buona soluzione, forse meglio optare per una lista. | Cioé, come? |
Una lista è un elenco di elementi -ognuno allocato dinamicamente- che contengono un campo 'puntatore al prossimo elemento' (almeno nel caso più semplice, le liste semplici, appunto).
Basta avere definito staticamente il puntatore al primo elemento e poi si tratta di 'saltare' da ognuno al successivo finchè non si trova quello desiderato. Per rimuoverlo basta fare sì che l'elemento precedente a quello da rimuovere punti al successivo (sempre di quello da rimuovere) e poi si può deallocare tranquillamente l'elemento da cancellare.
(se ti interessa l'argomento, è spiegato meglio ad esempio qui ... )
 |
|
Top |
|
 |
chemicalbit Dio maturo


Registrato: 01/04/05 18:59 Messaggi: 18597 Residenza: Milano
|
Inviato: 26 Set 2008 12:17 Oggetto: |
|
|
Ah sì, ho capito, una lista in cui ogni elemento punta al successivo.
(Una sua "evoluzione" è consentire delel diramazioni, creando degli "alberi", giusto?) |
|
Top |
|
 |
SverX Supervisor Macchinisti


Registrato: 25/03/02 12:16 Messaggi: 11809 Residenza: Tokelau
|
Inviato: 26 Set 2008 16:47 Oggetto: |
|
|
chemicalbit ha scritto: | Ah sì, ho capito, una lista in cui ogni elemento punta al successivo.
(Una sua "evoluzione" è consentire delel diramazioni, creando degli "alberi", giusto?) |
Un albero è un concetto topografico, è un grafo connesso e privo di cicli, e si può creare utilizzando delle liste multiple (ovvero delle liste che puntano a più di un altro nodo... se poi il numero di nodi a cui ognuno può puntare fosse variabile allora converrà che ogni nodo abbia una propria lista di collegamenti ai nodi...)
(dopo essermi scervellato a pensare come spiegarlo ho trovato una spiegazione migliore qui... ) |
|
Top |
|
 |
saetta Eroe in grazia degli dei

Registrato: 25/02/08 11:52 Messaggi: 129
|
Inviato: 09 Mar 2010 12:45 Oggetto: Ancora su free()... |
|
|
Salve... a me questa free non sta proprio simpatica...
Mi stavo chiedendo, quando è effettivamente necessario, dopo una chiamata a "free(ptr)" effettuare anche una "ptr = NULL" .
Come noto la "free" rende nuovamente disponibile la memora puntata da "ptr" ma esso continua a puntare a quell'area, giusto?
E allora... quando non si puo' far a meno di fare
Codice: |
{
...
free(ptr);
ptr = NULL;
...
} |
???
Grazie. |
|
Top |
|
 |
freemind Supervisor sezione Programmazione


Registrato: 04/04/07 21:28 Messaggi: 4643 Residenza: Internet
|
Inviato: 09 Mar 2010 12:52 Oggetto: |
|
|
La free libera la memoria quindi fisicamente questa ridiventa disponibile.
La parte "libera la memoria" va intesa come "libera la cella di memoria puntata dal puntatore".
Ptr fisicamente occupa 32bit e questi non vengono liberati mai (neppure con il NULL) perchè free non libera la memoria occupata dal puntatore ma quella puntata dallo stesso.
Forse un po' crocchio come giro però devi distinguere la memoria puntata da quella occupata dal puntatore stesso. |
|
Top |
|
 |
SverX Supervisor Macchinisti


Registrato: 25/03/02 12:16 Messaggi: 11809 Residenza: Tokelau
|
Inviato: 09 Mar 2010 16:29 Oggetto: Re: Ancora su free()... |
|
|
saetta ha scritto: | Come noto la "free" rende nuovamente disponibile la memora puntata da "ptr" ma esso continua a puntare a quell'area, giusto? |
Sì, continua a valere quello che valeva prima e quindi a puntare ad un'area di memoria non riservata nello heap. Di conseguenza è da non usare più, a meno di non avere una nuova malloc() |
|
Top |
|
 |
saetta Eroe in grazia degli dei

Registrato: 25/02/08 11:52 Messaggi: 129
|
Inviato: 09 Mar 2010 23:58 Oggetto: |
|
|
Ok, questo mi è chiaro e ne deduco che la necessità di mettere a NULL un ptr che ha appena "subìto" una free() sopraggiunga in caso di controlli su di esso, dopo una free(). O no ?
Codice: |
...
if(cond)
{
free(ptr);
ptr = NULL;
}
if (ptr == NULL)
fai_qualcosa();
|
|
|
Top |
|
 |
freemind Supervisor sezione Programmazione


Registrato: 04/04/07 21:28 Messaggi: 4643 Residenza: Internet
|
Inviato: 10 Mar 2010 00:32 Oggetto: |
|
|
Quello che hai scritto ci sta!
L'usare NULL serve ad avere un valore che sia in qualche modo distinguibile dai possibili contenuti che può assumere la variabile.
NULL vuol dire "niente" quindi se il tuo puntatore è NULL vuol dire che non sta puntando a nulla.
In pratica il tuo codice potrebbe essere riscritto con una sentinella tipo:
Codice: |
...
setinella=1;
if(cond)
{
free(ptr);
sentinella=0;
}
if (sentinella==0)
{
fai_qualcosa(); // tra cui riassegnare ptr anche se non lo hai messo a NULL
}
|
In pratica NULL è un valore neutro che può essere assegnato ai puntatori per dire che in quel momento è disponibile oppure per indicare qualunque altra cosa.
Codice: |
ptr=NULL;
ptr=&a;
|
in entrambi i casi la variabile ptr è allocata nello stack e occupa 32bit; la memoria che viene liberata con free e allocata con malloc/calloc è quella dello heap. |
|
Top |
|
 |
SverX Supervisor Macchinisti


Registrato: 25/03/02 12:16 Messaggi: 11809 Residenza: Tokelau
|
Inviato: 10 Mar 2010 17:12 Oggetto: |
|
|
saetta ha scritto: | Ok, questo mi è chiaro e ne deduco che la necessità di mettere a NULL un ptr che ha appena "subìto" una free() sopraggiunga in caso di controlli su di esso, dopo una free(). O no ? |
Niente ti vieta di mettere a NULL un puntatore e poi di fare dei test sul puntatore per capire se sta puntando a qualcosa o no, ma non c'è una reale necessità. Ad esempio in una lista se rimuovi un elemento non hai bisogno di mettere a NULL il membro puntatore all'elemento successivo, tanto stai buttando via tutto, che ti frega? Idem per una variabile locale:
Codice: | void function finta (item* myItem) {
item* ptr = myItem->next;
rimuovi(ptr);
} |
a che servirebbe mettere ptr a NULL? |
|
Top |
|
 |
saetta Eroe in grazia degli dei

Registrato: 25/02/08 11:52 Messaggi: 129
|
Inviato: 10 Mar 2010 18:52 Oggetto: |
|
|
Grazie ragazzi, ora è un po' più chiaro... e spero di non dover litigare nuovamente con free() altrimenti questo topic diventa kilometrico...  |
|
Top |
|
 |
freemind Supervisor sezione Programmazione


Registrato: 04/04/07 21:28 Messaggi: 4643 Residenza: Internet
|
Inviato: 10 Mar 2010 19:49 Oggetto: |
|
|
saetta ha scritto: | Grazie ragazzi, ora è un po' più chiaro... e spero di non dover litigare nuovamente con free() altrimenti questo topic diventa kilometrico...  |
Io ti auguro di non aver più problemi con la funzione free() però anche se il 3d diventa kilometrico non c'è nessun problema, anzi, vuol dire che c'è ancora chi si diverte con il C!!!!
bauuuu |
|
Top |
|
 |
saetta Eroe in grazia degli dei

Registrato: 25/02/08 11:52 Messaggi: 129
|
Inviato: 11 Mar 2010 00:14 Oggetto: |
|
|
E invece...rieccomi...
se ho una struct che come membri oltre che tipi di dato "classici" (int, char, array ecc.) anche PUNTATORI A FUNZIONI...
all'atto della cancellazione della struct devo fare per ogni "membro-ptr a funzione" questo(?):
Codice: |
free((mystruct)->ptr_a_fne1);
free((mystruct)->ptr_a_fne2);
...
free((mystruct)->ptr_a_fneN);
|
oppure semplicemente, essendo puntatori a funzione mi dealloco la struct e via?
Nel primo caso credo di deallocare anche la memoria riservata alla funzione (membro di struct) mentre nel secondo elimino semplicemente il riferimento ad essa...o no?
LOL non troverò mai pace con il C...soprattutto a quest'ora...buonanotte! |
|
Top |
|
 |
SverX Supervisor Macchinisti


Registrato: 25/03/02 12:16 Messaggi: 11809 Residenza: Tokelau
|
Inviato: 11 Mar 2010 16:59 Oggetto: |
|
|
ma no, non devi deallocare nessun puntatore a funzione, mica hai allocato dello spazio nello heap!
In pratica non devi mai fare free() di niente che non hai allocato con una malloc(). Per dire, se hai una struct definita come variabile globale e poi punti a quella con un puntatore, poi mica usi la free().
Invece se hai un puntatore che usi per puntare ad una struttura che hai malloc()-ato nello heap allora sì, devi deallocare prima di usare il puntatore per altro/perderti il puntatore, altrimenti avrai un c.d. memory leak |
|
Top |
|
 |
SverX Supervisor Macchinisti


Registrato: 25/03/02 12:16 Messaggi: 11809 Residenza: Tokelau
|
Inviato: 11 Mar 2010 17:02 Oggetto: |
|
|
freemind ha scritto: | [...] anzi, vuol dire che c'è ancora chi si diverte con il C!!! |
problemi?  |
|
Top |
|
 |
freemind Supervisor sezione Programmazione


Registrato: 04/04/07 21:28 Messaggi: 4643 Residenza: Internet
|
Inviato: 11 Mar 2010 17:17 Oggetto: |
|
|
SverX ha scritto: | freemind ha scritto: | [...] anzi, vuol dire che c'è ancora chi si diverte con il C!!! |
problemi?  |
Aò, guarda che io sono quello di "Sesso Alcool e C++" mica bau bau micio micio!
Il C è una gran cosa e il mio commento era sincero!
Non trattarmi male SverX, sono sensibile!
Fine ot |
|
Top |
|
 |
|