Rekursivt frigjøre C structs

stemmer
3

Jeg har en struct som bare inneholder pekere til minne som jeg har tildelt. Er det en måte å rekursivt frigjøre hvert element som er en peker i stedet for å ringe gratis på hver av dem?

For eksempel, la oss si at jeg har dette oppsettet:

typedef struct { ... } vertex;
typedef struct { ... } normal;
typedef struct { ... } texture_coord;

typedef struct
{
    vertex* vertices;
    normal* normals;
    texture_coord* uv_coords;
    int* quads;
    int* triangles;
} model;

Og i min kode malloc jeg hver av de structs å lage en modell:

model* mdl = malloc (...);
mdl->vertices = malloc (...);
mdl->normals = malloc (...);
mdl->uv_coords = malloc (...);
mdl->quads = malloc (...);
mdl->triangles = malloc (...);

Det er enkelt å frigjøre hver pekeren som så:

free (mdl->vertices);
free (mdl->normals);
free (mdl->uv_coords);
free (mdl->quads);
free (mdl->triangles);
free (mdl);

Er det en måte jeg kan rekursivt iterere gjennom pekere i MDL stedet for å ringe gratis på hvert element?

( I praksis er det knapt noe arbeid å bare skrive gratis () for hver enkelt, men det vil redusere kode duplisering og være nyttig å lære av )

Publisert på 03/06/2009 klokken 01:14
kilden bruker
På andre språk...                            


8 svar

stemmer
18

Ikke egentlig - selv om du kan skrive en metode for å gjøre alle seks frigjør slik at du aldri går glipp av en.

void freeModel( model* md1 ) {
    free (mdl->vertices);
    free (mdl->normals);
    free (mdl->uv_coords);
    free (mdl->quads);
    free (mdl->triangles);
    free (mdl);
}
Svarte 03/06/2009 kl. 01:17
kilden bruker

stemmer
7

Det er ingen vei i C-språk for å gjøre dette, eller ville det være ønskelig - C ikke vet at hvert medlem er et tydelig peker tildelt via malloc og C inneholder ingen runtime typen info støtte til å gjøre dette - under kjøring på kompilert kode for å få tilgang til struct er bare ved hjelp av forskyvninger av av en base peker for hvert medlem tilgang.

Den enkleste måten ville være å skrive en "FreeModel" funksjon:

void FreeModel(model* mdl)
{
   free(mdl->vertices);
   ... // Other frees
   free(mdl);
}
Svarte 03/06/2009 kl. 01:20
kilden bruker

stemmer
6

Slik funksjonalitet er ikke bygget på til C, men du kan jukse litt ved å misbruke makro preprosessor:

#define XX_MODEL_POINTERS do { \
  xx(vertices); xx(normals); xx(uv_coords); xx(quads); xx(triangles); \
} while(0)

Å fordele:

model *mdl = malloc(sizeof(*mdl));
assert(mdl);
#define xx(N) mdl->N = malloc(sizeof(*mdl->N)); assert(mdl->N)
XX_MODEL_POINTERS;
#undef xx

Å frigjøre:

assert(mdl);
#define xx(N) free(mdl->N); mdl->NULL
XX_MODEL_POINTERS;
#undef xx
free(mdl);
mdl = NULL;

Den ekle bit er at definisjonen av struct modelog definisjonen av XX_MODEL_POINTERSkan bli gjensidig inkonsekvent, og det er ingen måte å fange den. Av denne grunn er det ofte bedre å generere definisjonen av XX_MODEL_POINTERSved parsing en .h fil et sted.

Metaprogramming i C er aldri lett.

Svarte 03/06/2009 kl. 01:52
kilden bruker

stemmer
3

Ta en titt på talloc http://talloc.samba.org/ hvis du gjør det:

model* mdl = talloc (NULL, ...);
mdl->vertices = talloc (mdl, ...);
mdl->normals = talloc (mdl, ...);
mdl->uv_coords = talloc (mdl, ...);
mdl->quads = talloc (mdl, ...);
mdl->triangles = talloc (mdl, ...);

du kan:

talloc_free(mdl);

og tallocvil ta seg av free'ing alle de andre blokkene du har ringt tallocmed mdlsom første argument ved tildeling tid (og det vil gjøre dette rekursivt kan du gjøre talloc(mdl->vertices, ...)og talloc_free(mdl);vil få det også)

Som en side er det en liten overhead til å bruke talloc fordi det er behov for å spore hva ting recurse over, men det er ikke veldig mye.

Svarte 17/06/2010 kl. 20:26
kilden bruker

stemmer
3

Du kan beregne størrelsen som trengs for dem alle sammen og gjøre en stor malloc

sizeof (modell) + sizeof (vertex) * nVertices ... etc.

Tildeling av svaret til MDL, resultat + sizeof (modell) til Modell-> vertekser ...

Så for å frigjøre det er bare en gratis.

Du må kanskje bekymre innretting problemer (avhengig av plattform), men det bør ikke være for vanskelig å finne ut. Det andre problemet er at det er en mye større del som kan utgjøre et problem hvis i en hukommelse begrenset miljø.

Svarte 03/06/2009 kl. 01:21
kilden bruker

stemmer
2

Kast alle de gratis er i funksjon?

Svarte 03/06/2009 kl. 01:18
kilden bruker

stemmer
0

Ikke med disse strukturene. Du kan legge til en annen inngang til på øverste nivå 'modell' struct som inneholder en liste over pekere til å bli satt fri, og gjenta den listen. Men jeg tviler på om den ekstra kompleksitet og redusert forståelighet av at løsningen ville være verdt det. (Med mindre du har en mye større og mer dypt nestet sett av oppføringer å frigjøre i topp-nivå 'modell' struct enn du viser her.)

Svarte 03/06/2009 kl. 01:18
kilden bruker

stemmer
0

Jeg tror ikke det er mulig i noen form for C.

Du kan kode en egen funksjon for den spesifikke strukturen der du vil passere pekere og fri dem der.

EDIT: Ups, for sent, så aldri disse svarene ...

Svarte 03/06/2009 kl. 01:18
kilden bruker

Cookies help us deliver our services. By using our services, you agree to our use of cookies. Learn more