2012-03-15 14 views
11

Il codice sottostante restituisce un indirizzo quando viene eseguito in Windows, anche se mi aspettavo che restituisse NULL.Perché malloc (0) restituisce un indirizzo non nullo in Windows?

int main() 
{ 
    char *ptr = NULL; 
    ptr = malloc(0); 
    printf("malloc returned = %u\n", ptr); 

} 

Cosa potrebbe aver richiesto un'implementazione di malloc? C'è qualche motivo dietro di esso?

Poiché, questa è una memoria da 0 byte, non ho sperimentato la scrittura di alcun dato. Ma questa memoria può essere usata per qualcosa?

risposta

9

E 'solo la dimensione minima si sta richiedendo. E poiché non ci sono blocchi di lunghezza zero nel mucchio Win32, è possibile:

void *p = malloc(0); 
// ... do some stuff in between... 
realloc(p, n); 

Che dovrebbe per lo più portare a riutilizzare un blocco del mucchio (se sei fortunato e la nuova dimensione è piccola). Una piccola ottimizzazione opportunistica (o un rallentamento, a seconda del contesto e dei livelli di caffè nel sangue).

Questo è un esempio semplificato. La situazione attuale potrebbe essere una classe che alloca un buffer quando viene creato e consente anche di accrescerlo. Se gli input sono fastidiosi da controllare, puoi semplicemente lasciare che faccia l'allocazione del buffer a dimensione zero.

+0

+1 come ho visto in realtà 1 persona che usa questo per il suo "vantaggio" quando non desiderava nulla di speciale in un ciclo che potesse far crescere la memoria di malloc'd/realloc'd molto grande. – JimR

+1

Tuttavia, è possibile passare un puntatore nullo in 'realloc', quindi questo trucco non è in alcun modo essenziale. Potresti anche "annullare * p = 0;". –

+0

@Steve Non è davvero un trucco. È un artefatto di programmazione e specifiche di piattaforma allentate. Senza test, non è chiaro come si comporterebbe HeapRealloc (heap, HEAP_REALLOC_IN_PLACE_ONLY, 0, 4), ad esempio. – ActiveTrayPrntrTagDataStrDrvr

7

Ecco risposta entro il comp.lang.c FAQ: http://c-faq.com/ansi/malloc0.html

L'ANSI/ISO standard dice che può compiere; il comportamento è definito dall'implementazione (vedi domanda 11.33). Il codice portatile deve fare attenzione a non chiamare malloc (0) o essere preparato per la possibilità di un ritorno nullo.

+0

Ma, cosa renderebbe un'implementazione scegliere di restituire un valore valido? Non ha senso restituire NULL in tutti i casi? – Jay

+3

Non necessariamente. Rabbrividisco agli scrittori del compilatore di seconda ipotesi, ma un implementatore potrebbe desiderare che malloc restituisca "null" solo se la memoria non può essere realmente allocata. – CAbbott

+1

@Jay: poiché l'implementazione è libera di fare entrambe le cose, potrebbe anche decidere di fare meno codice. È ragionevole decidere di non preoccuparsi di scrivere una riga aggiuntiva di codice per verificare l'input per 0 e restituire un puntatore nullo. Poi di nuovo, se l'implementazione ha già un test che la dimensione richiesta non è enormemente assurdamente (e restituirà un puntatore nullo se lo è), allora potrebbe essere altrettanto facile da controllare per assurdamente-enorme-o-zero. –

8

Per rispondere alla seconda parte della domanda no, la memoria non può essere utilizzata per nulla, poiché "la parte accessibile di esso" è 0 byte a partire dall'indirizzo restituito.

IIRC è tuttavia garantito che se l'implementazione restituisce valori non nulli, sarà un diverso indirizzo da qualsiasi altro blocco di memoria attualmente assegnato. Quindi, in teoria, potresti usare l'indirizzo come ID univoco temporaneo (di tipo puntatore), anche se ovviamente ci sono molti altri modi per ottenere un ID univoco. E anche se lo aveste usato per questo, malloc(1) funzionerebbe altrettanto bene come malloc(0) ed essere più portabile.

0

Non è inutile. Ci si aspetta che i blocchi restituiti da malloc siano unici. Quindi ogni blocco restituito da malloc trasporta sia i dati all'interno del blocco sia un identificatore univoco per esso, essendo il suo indirizzo. Se quest'ultima proprietà è importante e il fatto che non contenga dati non è un problema, allora è utile.

Tuttavia, come già detto, è un ottimo modo per scrivere codice non portatile. Questo NON è la stessa cosa del codice illegale, tuttavia, ed è perfettamente valido per un'implementazione che lo supporti (come apparentemente fa Windows).

Problemi correlati