0

Ich möchte Speicher für einige Elemente einer Struktur zuweisen, die Zeiger auf andere kleine Strukturen sind. Wie kann ich Speicher auf die beste Weise zuordnen und entziehen? Ich weisen Speicher mit Einzel mallocWie reserviere ich Speicher für einige der Strukturelemente

typedef struct _SOME_STRUCT { 
    PDATATYPE1 PDatatype1; 
    PDATATYPE2 PDatatype2; 
    PDATATYPE3 PDatatype3; 

    ....... 

    PDATATYPE12 PDatatype12; 
} SOME_STRUCT, *PSOME_STRUCT; 

I-Speicher wollen für PDatatype1,3,4,6,7,9,11.Can zuzuordnen:

Ex? Oder was ist der beste Weg, Speicher nur für diese Elemente zu reservieren und den gesamten zugewiesenen Speicher freizugeben?

Antwort

0

Wenn Ihre Struktur, die anderen Strukturen als Elemente anstelle von Zeigern enthält, können Sie Speicher für die kombinierte Struktur in einem Schuss zuordnen:

typedef struct _SOME_STRUCT { 
    DATATYPE1 Datatype1; 
    DATATYPE2 Datatype2; 
    DATATYPE3 Datatype3; 

    ....... 

    DATATYPE12 Datatype12; 
} SOME_STRUCT, *PSOME_STRUCT; 

PSOME_STRUCT p = (PSOME_STRUCT)malloc(sizeof(SOME_STRUCT)); 

// Or without malloc: 
PSOME_STRUCT p = new SOME_STRUCT(); 
+0

Wenn es andere structs hat statt ihren Zeiger es sie direkt durch 'SOME_STRUCT' verwenden kann, ohne das Zuweisen von Speicher, kann ich nicht ? – Ron

+0

Ja, wenn Sie eine Variable wie folgt definieren: 'SOME_STRUCT s;' –

+0

Aber ich muss nur Zeiger verwenden. – Ron

1

Es ist ein Trick, der einen einzigen malloc erlaubt, aber das muss auch dagegen abgewogen werden, einen mehrfachen Standard malloc Ansatz zu tun.

Wenn [und nur wenn], sobald die DatatypeN Elemente SOME_STRUCT zugeordnet sind, tun sie nicht in irgendeiner Weise neu verteilt werden müssen, noch haben jeder anderer Code tun, um ein free auf einem sie, können Sie die folgende [die Annahme, dass PDATATYPEn Punkte DATATYPEn] tun:

PSOME_STRUCT 
alloc_some_struct(void) 
{ 
    size_t siz; 
    void *vptr; 
    PSOME_STRUCT sptr; 

    // NOTE: this optimizes down to a single assignment 
    siz = 0; 
    siz += sizeof(DATATYPE1); 
    siz += sizeof(DATATYPE2); 
    siz += sizeof(DATATYPE3); 
    ... 
    siz += sizeof(DATATYPE12); 

    sptr = malloc(sizeof(SOME_STRUCT) + siz); 

    vptr = sptr; 
    vptr += sizeof(SOME_STRUCT); 

    sptr->Pdatatype1 = vptr; 
    // either initialize the struct pointed to by sptr->Pdatatype1 here or 
    // caller should do it -- likewise for the others ... 
    vptr += sizeof(DATATYPE1); 

    sptr->Pdatatype2 = vptr; 
    vptr += sizeof(DATATYPE2); 

    sptr->Pdatatype3 = vptr; 
    vptr += sizeof(DATATYPE3); 

    ... 

    sptr->Pdatatype12 = vptr; 
    vptr += sizeof(DATATYPE12); 

    return sptr; 
} 

Dann wird das, wenn Sie fertig sind, nur free(sptr) tun.

Die sizeof über sollte ausreichend sein, um eine ordnungsgemäße Ausrichtung für die Unterstrukturen bereitzustellen. Wenn nicht, müssen Sie sie durch ein Makro ersetzen (z. B. SIZEOF), das die erforderliche Ausrichtung bietet. (ZB) für 8-Byte-Ausrichtung, so etwas wie:

#define SIZEOF(_siz) (((_siz) + 7) & ~0x07) 

Hinweis: Während es möglich ist, all dies zu tun, und es ist häufiger für Dinge wie variabler Länge Zeichenfolge structs wie:

struct mystring { 
    int my_strlen; 
    char my_strbuf[0]; 
}; 

struct mystring { 
    int my_strlen; 
    char *my_strbuf; 
}; 

Es ist fraglich, ob es die [potentielle] Fragilität wert ist (dh jemand vergisst und macht die realloc/free auf den einzelnen Elementen). Der sauberere Weg wäre, die tatsächlichen Strukturen anstelle der Zeiger auf sie einzubetten, wenn die einzelne malloc eine hohe Priorität für Sie hat.

Ansonsten tun Sie einfach den [mehr] Standard Weg und tun die 12 individuellen malloc Anrufe und später die 12 free Anrufe.

Dennoch ist es ist eine praktikable Technik, insbesondere auf kleinen Speicher beschränkt Systeme. Hier

ist die [mehr] gewohnte Weise beteiligt pro-Element Zuweisungen:

PSOME_STRUCT 
alloc_some_struct(void) 
{ 
    void *vptr; 
    PSOME_STRUCT sptr; 

    sptr = malloc(sizeof(SOME_STRUCT)); 

    // either initialize the struct pointed to by sptr->Pdatatype1 here or 
    // caller should do it -- likewise for the others ... 
    sptr->Pdatatype1 = malloc(sizeof(DATATYPE1)); 
    sptr->Pdatatype2 = malloc(sizeof(DATATYPE2)); 
    sptr->Pdatatype3 = malloc(sizeof(DATATYPE3)); 
    ... 
    sptr->Pdatatype12 = malloc(sizeof(DATATYPE12)); 

    return sptr; 
} 

void 
free_some_struct(PSOME_STRUCT sptr) 
{ 

    free(sptr->Pdatatype1); 
    free(sptr->Pdatatype2); 
    free(sptr->Pdatatype3); 
    ... 
    free(sptr->Pdatatype12); 

    free(sptr); 
} 
+0

Ich kann das tun, aber das Problem mit Klocwork ist, dass es darauf bestehen wird, den Rückgabewert für jeden malloc-Aufruf zu überprüfen! (Ich spreche über die Standard-Weise, die Sie erwähnt haben) – Ron

+0

Ich würde Ates Frage über warum warum Zeiger _must_ verwendet werden müssen. IMO, es sei denn, Sie müssen einzelne Elemente mit DATATYPEn anstelle von PDATATYPEn neu zuweisen, scheint besser. Jede Methode, die ich gepostet habe, sollte passen, da sie beide legitim sind. Aber ich wette, dass klocwork sich über den Trick beschweren wird. Es gibt jedoch eine Subpool-Zuweisungsmethode, die die Anzahl der mallocs reduzieren würde. Wenn Sie Ihre Anforderungen/Einschränkungen ein wenig genauer erklären können, kann ich möglicherweise meine Antwort entsprechend anpassen. –

+0

Es ist nur, dass ich eine vordefinierte Struktur verwenden muss, die jemand früher in meinem Projekt definiert hat, und es wurde an verschiedenen anderen Orten verwendet, so dass ich die Struktur selbst nicht ändern kann. – Ron