GNU/Linux >> Linux Esercitazione >  >> Linux

Cosa restituisce malloc(0)?

Altri hanno risposto come malloc(0) lavori. Risponderò a una delle domande che hai posto a cui non è stata ancora data risposta (credo). La domanda riguarda realloc(malloc(0), 0) :

Cosa significa malloc(0) Restituzione? La risposta sarebbe la stessa per realloc(malloc(0),0) ?

Lo standard dice questo su realloc(ptr, size) :

  • se ptr è NULL , si comporta come malloc(size) ,
  • altrimenti (ptr non è NULL ), rilascia il vecchio puntatore all'oggetto tramite ptr e restituisce un puntatore a un nuovo buffer allocato. Ma se size è 0, C89 dice che l'effetto è equivalente a free(ptr) . È interessante notare che non riesco a trovare quella dichiarazione nella bozza C99 (n1256 o n1336). In C89, l'unico valore sensato da restituire in quel caso sarebbe NULL .

Quindi, ci sono due casi:

  • malloc(0) restituisce NULL su un'implementazione. Poi il tuo realloc() chiamata è equivalente a realloc(NULL, 0) . Equivale a malloc(0) dall'alto (e questo è NULL in questo caso).
  • malloc(0) restituisce diverso da NULL . Quindi, la chiamata equivale a free(malloc(0)) . In questo caso, malloc(0) e realloc(malloc(0), 0) non equivalente.

Nota che qui c'è un caso interessante:nel secondo caso, quando malloc(0) restituisce diverso da NULL in caso di successo, potrebbe comunque restituire NULL per indicare il fallimento. Ciò risulterà in una chiamata del tipo:realloc(NULL, 0) , che sarebbe equivalente a malloc(0) , che può restituire o meno NULL .

Non sono sicuro se l'omissione in C99 sia una svista o se significhi che in C99, realloc(ptr, 0) per non-NULL ptr non è equivalente a free(ptr) . Ho appena provato con gcc -std=c99 , e quanto sopra è equivalente a free(ptr) .

Modifica :Penso di capire qual è la tua confusione:

Diamo un'occhiata a uno snippet del tuo codice di esempio:

ptr = malloc(0);
if (ptr == realloc(ptr, 1024))

Quanto sopra non è lo stesso di malloc(0) == realloc(malloc(0), 1024) . Nel secondo, il malloc() la chiamata viene effettuata due volte, mentre nella prima si passa un puntatore allocato in precedenza a realloc() .

Analizziamo prima il primo codice. Supponendo malloc(0) non restituisce NULL in caso di successo, ptr ha un valore valido Quando esegui realloc(ptr, 1024) , realloc() fondamentalmente ti dà un nuovo buffer che ha la dimensione 1024 e il ptr diventa invalido. Un'implementazione conforme può restituire lo stesso indirizzo di quello già presente in ptr . Quindi, il tuo if la condizione può restituire true. (Nota, tuttavia, osservando il valore di ptr dopo realloc(ptr, 1024) potrebbe essere un comportamento non definito.)

Ora la domanda che fai:malloc(0) == realloc(malloc(0), 1024) . In questo caso, supponiamo che sia il file malloc(0) sulla sinistra e sulla destra restituisce non-NULL . Quindi, sono garantiti per essere diversi. Inoltre, il valore restituito da malloc() sul lato sinistro non è stato free() d ancora, quindi qualsiasi altro malloc() , calloc() o realloc() potrebbe non restituire quel valore. Ciò significa che se hai scritto la tua condizione come:

if (malloc(0) == realloc(malloc(0), 1024)
    puts("possible");

non vedrai possible sull'output (a meno che sia malloc() e realloc() fallisce e restituisce NULL ).

#include <stdio.h>
#include <stdlib.h>

int main(void)
{
    void *p1;
    void *p2;

    p1 = malloc(0);
    p2 = realloc(p1, 1024);
    if (p1 == p2)
        puts("possible, OK");

    /* Ignore the memory leaks */
    if (malloc(0) == realloc(malloc(0), 1024))
        puts("shouldn't happen, something is wrong");
    return 0;
}

Su OS X, il mio codice non ha prodotto nulla quando l'ho eseguito. Su Linux, stampa possible, OK .


malloc(0) è Implementazione definita per quanto riguarda C99.

Da C99 [Sezione 7.20.3]

L'ordine e la contiguità dell'archiviazione allocata dalle chiamate successive alle funzioni calloc, malloc e realloc non sono specificate . Il puntatore restituito se l'allocazione ha successo è opportunamente allineato in modo che possa essere assegnato a un puntatore a qualsiasi tipo di oggetto e quindi utilizzato per accedere a tale oggetto o a un array di tali oggetti nello spazio allocato (fino a quando lo spazio non viene esplicitamente deallocato). La durata di un oggetto allocato si estende dall'allocazione fino alla deallocazione. Ciascuna di tali allocazioni produrrà un puntatore a un oggetto disgiunto da qualsiasi altro oggetto. Il puntatore restituito punta all'inizio (indirizzo di byte più basso) dello spazio allocato. Se non è possibile allocare lo spazio, viene restituito un puntatore nullo. Se la dimensione dello spazio richiesto è zero, il comportamento è definito dall'implementazione :viene restituito un puntatore nullo o il comportamento è come se la dimensione fosse un valore diverso da zero, tranne per il fatto che il puntatore restituito non deve essere utilizzato per accedere a un oggetto.


In C89, malloc(0) dipende dall'implementazione - non so se C99 lo abbia risolto o meno. In C++, usando:

char * p = new char[0];

è ben definito:ottieni un puntatore valido, non nullo. Naturalmente, non puoi utilizzare il puntatore per accedere a ciò a cui punta senza invocare un comportamento indefinito.

Per quanto riguarda il motivo per cui esiste, è conveniente per alcuni algoritmi e significa che non è necessario sporcare il codice con test per valori zero.


Linux
  1. Cosa fa Bamfdaemon?

  2. Che cosa restituisce il comando Ls -al .*?

  3. Cosa significa 'cd-'?

  4. Cosa fa ulimit -s illimitato?

  5. Cosa produce pwd?

Cosa fa effettivamente Libgl_always_indirect=1?

Cosa fa . ~/.bashrc Comando Fare??

Cosa fa poll() con un timeout pari a 0?

Quale codice di errore restituisce un processo che restituisce i segfault?

Cosa fa 'bash -c'?

Cosa fa esattamente init?