2010-02-02 34 views
25
struct foo 
{ 
    int a; 
    int b; 
}; 

void* p = (void*)malloc(sizeof(struct foo)); 
((foo*)p)->a;//do something. 
free(p);//Is this safe? 
+1

Ist das überhaupt gültig C? Sollte das nicht die Größe von (struct foo) sein?:) –

+2

Nicht nur ist es OK zu 'free()' ein 'void *' Wert, per Definition, alle 'free()' sieht immer ist ein 'void *', also technisch ist alles befreit in C 'void * ': –

+0

@Daniel - Wenn du mich fragst, sollte es' struct foo * p = malloc (sizeof * p)) sein; 'aber was weiß ich? –

Antwort

31

Ja.

malloc liefert void * und frei nimmt void *, so einige Ihrer Würfe sind bedeutungslos, und du bist zu befreien immer ein void *, auch wenn Sie mit einer anderen Art von Zeiger fangen.

1

Ja, es ist sicher.

5

Ja - free nimmt einen Zeiger auf void, also wenn Sie es aufrufen, wird der Zeiger (implizit) auf einen Zeiger auf Void in jedem Fall umgewandelt.

Der Rest des Codes ist nicht ganz so sicher:

void* p = (void*)malloc(sizeof(foo)); 

Sie sollten nicht werfen die Rückkehr von malloc (in C). Dies kann den Fehler des Vergessens abdecken #include <stdlib.h>

3

Ja. Der Funktionsprototyp für free ist auch:

void free(void *ptr); 
13

Ja, es ist sicher. Bei der Zuweisung von Speicher verfolgt die Laufzeitbibliothek die Größe jeder Zuordnung. Wenn Sie free() aufrufen, sucht es die Adresse, und wenn es eine Zuordnung für diese Adresse findet, wird die richtige Menge an Speicher freigegeben (der Block, der an dieser Adresse zugewiesen wurde).

2

Vielleicht ist es nicht fühlen sicher wegen der Magie passiert hinter den Kulissen. Die C-Laufzeit und/oder das Betriebssystem selbst verfolgen aktiv den von malloc zurückgegebenen Speicher, einschließlich seiner Größe und seines Standorts. Obwohl es sich anfühlt, als würden Sie einen typlosen Zeiger wieder auf free() übergeben, übergeben Sie tatsächlich einen Verweis auf ein Objekt, das der Speichermanager aktiv verfolgt.

3

in C ist es vollkommen sicher, weil es keine Destruktoren zu nennen gibt.

Das Speichersystem verfolgt die Größe der Zuordnungen.

In C++ müssen Sie den gleichen Typ löschen, den Sie neu haben, einschließlich des delete [] -Operators, um neue Arrays zu löschen.

Dies ist nur um sicherzustellen, dass Destruktoren aufgerufen werden.

0

Ja, aber normalerweise ist es ein Zeichen für schlechtes Design. malloc() wird normalerweise zum Zuweisen von Puffern (große Arrays desselben primitiven Typs) oder von Objekten (Strukturen mit initialisierten Feldern) verwendet. so

unsigned char *rgba_buffer = malloc(width * hieght * 4); 
    /* use the buffer here */ 
    free(rgba_buffer); 

    BITSTREAM *bs = bitstream("bitfile.boin"); 
    /* use the bitstream here */ 
    destroy_bitstream(bs); 

    typedef struct 
    { 
    FILE *fp; 
    unsigned char ch; 
    int index; 
    } BITSTREAM; 


    BITSTREAM *bitstream(const char *filename) 
    { 
     BITSTREAM *bs = malloc(sizeof(BITSTREAM)); 
     bs->fp = fopen(filename "rb"); 
     /* etc */ 
     return bs; 
    } 

    void destroybitstream(BITSTREAM *bs) 
    { 
    if(bs) 
    { 
     if(bs->fp) 
      fclose(bs->fp); 
     free(bs); 
    } 
    } 

In einem Fall malloc und frei Spiel, in den andere die zugewiesenen Speicher zurückgeführt werden, gibt es auch sekundäre Ressourcen und den Konstruktor und Destruktor Match In beiden Fällen sollte die malloc und die freie entspricht. Es sollte selten sein, eine Speicherregion zuzuweisen, aber nicht, wofür sie verwendet wird. Und Sie sollten nicht Zuteilungen interleaving und chaotisch freigibt.

Moderne C++ strafft dies mit eindeutigen Zeigern, die das Objekt "besitzen". Während Sie einen eindeutigen Zeiger auf Void haben können, wäre es sehr selten.

Verwandte Themen