2009-06-03 8 views
3

할당 한 메모리에 대한 포인터 만 포함하는 구조체가 있습니다. 재귀 적으로 각 요소를 자유롭게 호출하는 대신 포인터 인 각 요소를 해제하는 방법이 있습니까?C 구조체를 재귀 적으로 해제합니다.

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

그것은 각 포인터를 무료로 간단합니다 :

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; 

그리고 내 코드에서

내가 모델을 생성하기 위해 구조체의 각각의 malloc : 예를 들어

,의 내가이 레이아웃을 가정 해 봅시다 그래서 :

반복적으로 mdl rathe의 포인터를 반복 할 수있는 방법이 있습니까? 각 요소를 무료로 호출하는 것보다?

(실제로 는 단지 각각에 대해 free()를 작성하는 거의 모든 작업,하지만 그것은 코드 중복을 줄이고 배울 도움이 될 것입니다)별로

답변

6

이러한 기능은 C에 내장되지 않은,하지만 당신은 매크로 전처리 남용에 의해 약간의 속임수 수 있습니다

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

가 해제하려면 :

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

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

가 할당을

더러운 비트는 struct model의 정의와의 정의입니다.은 서로 불일치가 될 수 있으며이를 포착 할 방법이 없습니다. 이런 이유로 어딘가에서 .h 파일을 구문 분석하여 XX_MODEL_POINTERS의 정의를 생성하는 것이 더 좋습니다.

C에서의 메타 프로그래밍은 결코 쉬운 일이 아닙니다. 당신이 경우에

+1

아, 감사합니다! 이 솔루션은 더러워 보일지라도 성능 저하없이 코드 중복을 피할 수 있으며 이전에 보지 못한 접근 방식입니다. 아마 실제로는 사용하지 않겠지 만 코드를 다시 구성하는 것보다 흥미로운 구현으로 제 질문을 해결할 것입니다. – Kai

+0

매번 매크로를 다시 정의 할 필요없이 매크로에 대한 인수를 수행 할 수 있습니까? –

+0

나는 여기에 '학대'라는 단어를 남용한다고 생각합니다. 이런 식으로 전처리 기가 만들어 졌다고 생각합니다. 악용 사례 -> 사용 :) – Gewure

18

을 - 당신이하는 방법을 쓸 수 있지만, 여섯 개의 자유를 모두 놓치지 않도록하십시오.

void freeModel(model* md1) { 
    free (mdl->vertices); 
    free (mdl->normals); 
    free (mdl->uv_coords); 
    free (mdl->quads); 
    free (mdl->triangles); 
    free (mdl); 
} 
2

무료로 모든 것을 던집니다.

0

내가 C.

당신은 당신이 포인터를 전달하고 그들을 거기 무료 것이라고 특정 구조에 대해 별도의 기능을 코딩 할 수있는 어떤 형태로 가능을 믿지 않는다.

편집 : UPS, 너무 늦게, 그 대답 ... 그 구조와

0

되지 않음을 본적이 없어요. 해제 할 포인터 목록을 포함하는 최상위 'model'구조체에 다른 항목을 추가하고 해당 목록을 반복 할 수 있습니다. 그러나 그 솔루션의 복잡성이 줄어들고 이해가 용이하지 않은 것이 그만한 가치가 있는지 의심 스럽습니다. (당신이 여기에 보여주는 것보다 더 많이 크고 깊게 중첩 된 항목을 최상위 '모델'구조체에서 해제하지 않는 한)

7

C 언어에서이를 수행 할 방법이 없습니다 - C는 각 멤버가 malloc을 통해 할당 된 별개의 포인터라는 것을 알지 못한다. C는 런타임시 타입 정보 지원을 포함하지 않는다. 런타임시에는 구조체에 접근하기위한 컴파일 된 코드는 단지 offsets를 off로 사용하고있다. 각 멤버 액세스에 대한 기본 포인터

가장 간단한 방법은 "FreeModel"함수를 작성하는 것입니다 :

void FreeModel(model* mdl) 
{ 
    free(mdl->vertices); 
    ... // Other frees 
    free(mdl); 
} 
3

당신 수 함께 그들 모두에 필요한 크기를 계산하고 하나 개의 큰 malloc에 ​​

를 sizeof (모델) 할 +를 sizeof 등

(정점) * nVertices ... 그런 다음

는 한 FRE입니다 무료로 ...> 정점을 모델 -에, 결과 +를 sizeof (모델) MDL하는 결과를 할당 이자형.

정렬 문제 (플랫폼에 따라 다름)에 대해 걱정할 필요가 있지만 알아 내기가 어렵지 않을 수 있습니다.다른 문제는 메모리가 제한된 환경에서 문제가 발생할 수있는 훨씬 큰 청크입니다.

3

talloc http://talloc.samba.org/를 살펴 보자 :

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, ...); 

당신은 할 수 있습니다

talloc_free(mdl); 

talloc는 'free 돌봐 당신이 mdltalloc라는 다른 모든 블록을 보내고 것 할당 시간에 첫 번째 인수로 (그리고 이것은 재귀 적으로 수행 할 수 있습니다. talloc(mdl->vertices, ...)talloc_free(mdl);도 마찬가지입니다)

제쳐두고 talloc을 사용하는 데 약간의 오버 헤드가 있습니다. 왜냐하면 어떤 물건이 반복되는지 추적해야하기 때문입니다.

관련 문제