52 votes

Que retourne malloc (0)?

Qu'est - malloc(0) retours? La réponse serait-elle la même pour 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;
}

La sortie de linux gcc:

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

La sortie cessent de changer à chaque fois pour malloc(0). Est-ce une réponse? Et pourquoi quelqu'un serait-il intéressé par un pointeur, d'autres que de la recherche académique?

EDIT:

Si malloc(0) retours mannequin pointeur, puis comment les travaux suivants:

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

EDIT:

Le code suivant affiche "possible" pour chaque itération. Pourquoi devrait-il pas manqué ?

#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;
}

41voto

Alok Singhal Points 33073

D'autres ont répondu à combien de malloc(0) travaux. Je vais répondre à une des questions que vous avez demandé n'a pas encore reçu de réponse (je pense). La question est à propos de realloc(malloc(0), 0):

Qu'est - malloc(0) de retour? La réponse serait-elle la même pour realloc(malloc(0),0)?

La norme dit ceci à propos de realloc(ptr, size):

  • si ptr est NULL, il se comporte comme malloc(size),
  • dans le cas contraire (ptr n'est NULL), il libère l'ancien pointeur d'objet par ptr et retourne un pointeur vers un nouveau tampon alloué. Mais si size 0, C89 dit que l'effet est équivalent à free(ptr). Il est intéressant de noter, je ne trouve pas que la déclaration C99 projet (n1256 ou n1336). En C89, la seule raisonnable de la valeur de retour dans ce cas serait NULL.

Donc, il y a deux cas:

  • malloc(0) retours NULL sur une mise en œuvre. Ensuite, votre realloc() appel est équivalent à realloc(NULL, 0). C'est l'équivalent de malloc(0) à partir de ci-dessus (et c'est - NULL dans ce cas).
  • malloc(0) rendements non-NULL. Alors, l'appel est équivalent à free(malloc(0)). Dans ce cas, malloc(0) et realloc(malloc(0), 0) sont pas équivalentes.

Notez qu'il est un cas intéressant ici: dans le deuxième cas, lorsqu' malloc(0) rendements non-NULL sur le succès, il peut toujours renvoyer NULL pour indiquer l'échec. Cela se traduit par un appel comme: realloc(NULL, 0), ce qui équivaut à un malloc(0), ce qui peut ou ne peut pas retourner NULL.

Je ne suis pas sûr si l'omission en C99 est un oubli ou si elle signifie qu'en C99, realloc(ptr, 0) pour les non-NULL ptr n'est pas équivalent à free(ptr). J'ai juste essayé cela avec gcc -std=c99, et le ci-dessus est équivalent à free(ptr).

Edit: je crois que je comprends ce que votre confusion est:

Regardons un extrait de votre exemple de code:

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

Le ci-dessus n'est pas le même que malloc(0) == realloc(malloc(0), 1024). Dans le second, l' malloc() appel est effectué à deux reprises, alors que dans le premier, tu es de passage a été allouée pointeur realloc().

Analysons le premier le premier code. En supposant malloc(0) n'a pas de retour NULL sur le succès, ptr a une valeur valide. Lorsque vous effectuez realloc(ptr, 1024), realloc() vous donne essentiellement un nouveau tampon de la taille de 1024, et l' ptr devient non valide. Une mise en œuvre conforme peut renvoyer à la même adresse que l'on a déjà en ptr. Donc, votre if condition peut retourner la valeur true. (Notez, cependant, en regardant la valeur de ptr après realloc(ptr, 1024) peut être un comportement non défini.)

Maintenant, la question que vous posez: malloc(0) == realloc(malloc(0), 1024). Dans ce cas, supposons que les deux malloc(0) LHS et RHS renvoie non-NULL. Ensuite, ils sont garantis pour être différent. Aussi, la valeur de retour de malloc() LHS n'a pas été free()d encore, de sorte que toute les autres malloc(), calloc()ou realloc() peut ne pas renvoyer cette valeur. Cela signifie que si vous avez écrit votre condition que:

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

vous ne verrez possible sur la sortie (à moins que les deux malloc() et realloc() échouer et renvoyer 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;
}

Sur OS X, mon code n'a pas de sortie de quelque chose quand je l'ai couru. Sur Linux, il imprime possible, OK.

34voto

Prasoon Saurav Points 47488

malloc(0) est mise en Œuvre Définie comme la mesure du C99.

De C99 [Section 7.20.3]

L'ordre et la contiguïté de stockage alloué par les appels successifs à la calloc, malloc et realloc fonctions n'est pas spécifié. Le pointeur retourné si la répartition réussit est correctement alignés de sorte qu'il peut être attribué à un pointeur vers n'importe quel type d'objet et ensuite utilisé pour accéder à un tel objet ou un tableau de ces objets dans l'espace alloué (jusqu'à ce que l'espace est explicitement libéré). La durée de vie d'un objet alloué s'étend de l'allocation jusqu'à la libération. Chaque allocation doit permettre un pointeur vers un objet disjoints de tout autre objet. Le pointeur retourné points de départ (le plus faible de l'octet l'adresse) de l'espace alloué. Si l'espace ne peut pas être attribué, un pointeur null est retournés. Si la taille de l'espace requis est égal à zéro, le comportement est mise en œuvre- défini: soit un pointeur null est retourné, ou le comportement est comme si la taille avait quelques valeur différente de zéro, sauf que le pointeur retourné ne doit pas être utilisé pour accéder à un objet.

5voto

Kornel Kisielewicz Points 26556

Norme C99

Si l'espace ne peut pas être alloué, un nullpointer est renvoyé. Si la taille de l'espace demandé est égale à zéro, le comportement est défini par l'implémentation: un pointeur null est renvoyé ou le comportement est comme si la taille était une valeur différente de zéro, sauf que le pointeur renvoyé ne doit pas être utilisé pour accéder à un objet. .

4voto

unwind Points 181987

La FAQ comp.lang.c a le texte suivant :

La norme ANSI / ISO dit que cela peut être le cas; le comportement est défini par la mise en œuvre (voir la question 11.33). Le code portable doit soit veiller à ne pas appeler malloc (0), soit être préparé à la possibilité d’un retour à zéro.

Donc, il est probablement préférable d'éviter d'utiliser malloc(0) .

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X