Domanda

A questa domanda ha già una risposta qui:

Cosa malloc(0) restituisce?La risposta sarebbe essere lo stesso per realloc(malloc(0),0) ?

#include<stdio.h>
#include<malloc.h>
int main()
{
        printf("%p\n", malloc(0));
        printf("%p\n", realloc(malloc(0), 0));
        return 0;
}

Uscita dal gcc linux:

manav@manav-workstation:~$ gcc -Wall mal.c
manav@manav-workstation:~$ ./a.out
0x9363008
(nil)
manav@manav-workstation:~$

L'uscita continuano a cambiare ogni volta per malloc(0).Questa è una risposta standard?E perché qualcuno dovrebbe essere interessato a ottenere un puntatore, altri meno accademico e di ricerca?

EDIT:

Se malloc(0) restituisce il manichino di puntatore, quindi come si fa a seguenti opere:

int main()
{
    void *ptr = malloc(0);
    printf("%p\n", realloc(ptr, 1024));
    return 0;
}

EDIT:

Il codice seguente restituisce "possibile" per ogni iterazione.Perché non dovrebbe fallire ?

#include<stdio.h>
#include<malloc.h>
int main()
{

        int i;
        void *ptr;
        printf("Testing using BRUTE FORCE\n");
        for (i=0; i<65000; i++)
        {
                ptr = malloc(0);
                if (ptr == realloc(ptr, 1024))
                        printf("Iteration %d: possible\n", i);
                else
                {
                        printf("Failed for iteration %d\n", i);
                        break;
                }
        }
        return 0;
}
È stato utile?

Soluzione

Altri hanno risposto come funziona malloc(0). Risponderò una delle domande che ha chiesto che non è stato ancora risposto (credo). La domanda riguarda realloc(malloc(0), 0):

  

Che cosa significa malloc(0) tornare? La risposta sarebbe uguale per realloc(malloc(0),0)?

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

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

Quindi, ci sono due casi:

  • rendimenti malloc(0) NULL su un'implementazione. Poi la chiamata realloc() è equivalente a realloc(NULL, 0). Ciò equivale a malloc(0) dall'alto (e cioè NULL in questo caso).
  • malloc(0) ritorna non NULL. Poi, la chiamata è equivalente a free(malloc(0)). In questo caso, malloc(0) e realloc(malloc(0), 0) sono non equivalente.

Si noti che non v'è un caso interessante qui: nel secondo caso, quando malloc(0) ritorna non NULL in caso di successo, può ancora tornare NULL per indicare il fallimento. Questo si tradurrà in una chiamata, come:. realloc(NULL, 0), che sarebbe equivalente a malloc(0), che può o non può restituire NULL

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

Modifica : Credo di capire che cosa il vostro confusione è:

Diamo un'occhiata a un frammento dal codice di esempio:

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

È possibile che questo non è lo stesso di malloc(0) == realloc(malloc(0), 1024). Nel secondo, la chiamata malloc() viene effettuata due volte, mentre nel primo, si sta passando un puntatore precedentemente assegnato a realloc().

Analizziamo il primo codice prima. Supponendo malloc(0) non restituisce NULL in caso di successo, ptr ha un valore valido. Quando si esegue realloc(ptr, 1024), realloc() fondamentalmente si dà un nuovo buffer che ha le dimensioni 1024 e il ptr non è più valido. Un'implementazione conforme può restituire lo stesso indirizzo di quello già in ptr. Così, la sua condizione if può restituire vero. (Si noti, tuttavia, guardando il valore di ptr dopo realloc(ptr, 1024) possono essere undefined comportamento.)

Ora la domanda che si chiedono: malloc(0) == realloc(malloc(0), 1024). In questo caso, supponiamo che sia il malloc(0) sulla LHS e RHS ritorna non NULL. Poi, si sono garantiti per essere diverso. Inoltre, il valore restituito dal malloc() sul lato sinistro non è stato ancora free()d, in modo che qualsiasi altra malloc(), calloc() o realloc() non può restituire tale valore. Questo significa che se hai scritto la sua condizione come:

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

non si vedrà possible sull'uscita (a meno che non sia malloc() e realloc() non riescono e NULL ritorno).

#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 dato alcun output quando ho eseguito. Su Linux, stampa possible, OK.

Altri suggerimenti

malloc(0) è Attuazione Definiti per quanto C99 è interessato.

Da C99 [Sezione 7.20.3]

L'ordine e la contiguità di spazio di archiviazione allocato dalle chiamate successive alla calloc, malloc e realloc funzioni non è specificato.Il puntatore restituito se l'allocazione riesce opportunamente allineati in modo che possa essere assegnato ad un puntatore a qualsiasi tipo di oggetto e poi utilizzato per accedere ad un oggetto o un array di oggetti nello spazio destinato (fino a quando lo spazio è esplicitamente deallocato).Il ciclo di vita di un oggetto allocato si estende per l'assegnazione fino a quando la deallocazione.Ciascuno di tali quote sono resa un puntatore a un oggetto disgiunto da qualsiasi altro oggetto.Il puntatore restituito punti all'inizio (byte più basso indirizzo di spazio allocato.Se lo spazio non possono essere assegnati, un puntatore è null restituiti. Se la dimensione dello spazio richiesto è pari a zero, il comportamento di attuazione- definito:uno viene restituito un puntatore null, o il comportamento, è come se le dimensioni erano alcuni valore diverso da zero, tranne che il puntatore restituito non deve essere utilizzato per accedere a un oggetto.

In C89, malloc (0) è a carico di attuazione - non so se C99 ha fissato questo o no. In C ++, utilizzando:

char * p = new char[0];

è ben definito - si ottiene un, puntatore non nullo valida. Naturalmente, non è possibile utilizzare il puntatore per accedere a ciò a cui punta senza invocare un comportamento indefinito.

Per quanto riguarda il motivo per cui questo esiste, è conveniente per alcuni algoritmi, e significa che non c'è bisogno di lettiera il codice con i test per i valori zero.

standard di C99

  

Se lo spazio non può essere assegnato, un   nullpointer viene restituito. Se le dimensioni   dello spazio richiesto è pari a zero, il   comportamento dipende dall'implementazione:   sia un puntatore nullo viene restituito, o   il comportamento è come se fosse la dimensione   qualche valore diverso da zero, tranne che il   puntatore restituito non deve essere utilizzato per   accedere a un oggetto.

Il comp.lang.c FAQ ha la seguente dire:

  

L'ANSI / ISO standard dice che essa può   effettuare una; il comportamento è   implementazione definita (vedere la domanda   11.33). codice portabile deve o fare attenzione a non chiamare malloc (0), o essere   preparato per la possibilità di un nullo   tornare.

Quindi, probabilmente è meglio evitare di usare malloc(0).

Vedere C99, la sezione 7.20.3:

  

Se la dimensione dello spazio richiesto è   zero, il comportamento è   implementationdefined: o un nullo   puntatore viene restituito, o il comportamento   è come se la dimensione era un po 'diverso da zero   valore, salvo che la tornata   puntatore non deve essere utilizzato per accedere a un   oggetto.

Questo è valido per tutte le tre funzioni di allocazione (cioè calloc(), malloc() e realloc()).

Un punto a nessuno importava di parlare ancora, nel vostro primo programma è che realloc con la lunghezza 0 è la stessa cosa di free.

dalla pagina man di Solaris:

  

La funzione realloc() modifica la dimensione del blocco puntato        a da ptr a size byte e restituisce un puntatore al blocco (eventualmente spostato). I contenuti saranno invariate fino alla        minore dei vecchi e nuovi formati. Se ptr è NULL, realloc()        si comporta come malloc() per la dimensione specificata. Se size è 0        e ptr non è un puntatore nullo, lo spazio indicò viene fatta        disponibile per ulteriori allocazione dall'applicazione, però        non restituiti al sistema. La memoria è restituito al sistema        solo al momento della cessazione dell'applicazione.

Se non si sa che può essere una fonte di brutta sorpresa (mi è successo).

Penso che dipenda. Ho controllato le fonti di Visual Studio 2005 e ho visto questo nella funzione _heap_alloc:

if (size == 0)
    size = 1;

Credo che in molti casi può essere utile un puntatore valido, anche quando chiedono zero byte. Questo è perché questo comportamento coerente rende più facile per controllare i puntatori perché: se si dispone di un puntatore non-NULL è OK; se si dispone di un puntatore NULL probabilmente avete un problema. Ecco perché penso che la maggior parte delle implementazioni ritorneranno un puntatore valido, anche quando chiedono zero byte.

  

Se malloc (0) restituisce puntatore fittizia, allora come si fa in seguito a lavori:

     

void *ptr = malloc(0);

     

printf("%p\n", realloc(ptr, 1024));

Non so cosa si intende per "puntatore fittizio". Se malloc(0) restituisce non NULL, quindi ptr è un puntatore valido per un blocco di memoria di dimensioni pari a zero. L'implementazione malloc salva queste informazioni in un modo specifico dell'implementazione. realloc conosce la strada (attuazione specifiche) per capire che i punti ptr ad un blocco di memoria di dimensioni pari a zero.

(Come malloc / realloc / free farlo è specifico dell'implementazione. Una possibilità è quella di allocare 4 byte più richiesto e memorizzare la dimensione poco prima del blocco di memoria. In tal caso, ((int *)ptr)[-1] darebbe la dimensione del blocco di memoria, che è 0. non si dovrebbe mai fare questo dal codice, è solo per l'uso da realloc e free).

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top