GNU/Linux >> Tutoriels Linux >  >> Linux

Que retourne malloc(0) ?

D'autres ont répondu comment malloc(0) œuvres. Je vais répondre à l'une des questions que vous avez posées et qui n'a pas encore reçu de réponse (je pense). La question porte sur realloc(malloc(0), 0) :

Que signifie malloc(0) revenir? 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) ,
  • sinon (ptr n'est pas NULL ), il libère l'ancien pointeur d'objet de ptr et renvoie un pointeur vers un nouveau tampon alloué. Mais si size est 0, C89 indique que l'effet est équivalent à free(ptr) . Fait intéressant, je ne trouve pas cette déclaration dans le brouillon C99 (n1256 ou n1336). En C89, la seule valeur raisonnable à renvoyer dans ce cas serait NULL .

Donc, il y a deux cas :

  • malloc(0) renvoie NULL sur une implémentation. Puis votre realloc() call est équivalent à realloc(NULL, 0) . Cela équivaut à malloc(0) d'en haut (et c'est NULL dans ce cas).
  • malloc(0) renvoie non-NULL . Ensuite, l'appel est équivalent à free(malloc(0)) . Dans ce cas, malloc(0) et realloc(malloc(0), 0) ne sont pas équivalent.

Notez qu'il y a ici un cas intéressant :dans le second cas, quand malloc(0) renvoie non-NULL en cas de succès, il peut toujours renvoyer NULL pour indiquer un échec. Cela se traduira par un appel comme :realloc(NULL, 0) , ce qui équivaudrait à malloc(0) , qui peut ou non renvoyer NULL .

Je ne sais pas si l'omission dans C99 est un oubli ou si cela signifie que dans C99, realloc(ptr, 0) pour non-NULL ptr n'est pas équivalent à free(ptr) . Je viens d'essayer avec gcc -std=c99 , et ce qui précède est équivalent à free(ptr) .

Modifier :Je pense que je comprends votre confusion :

Regardons un extrait de votre exemple de code :

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

Ce qui précède n'est pas le même que malloc(0) == realloc(malloc(0), 1024) . Dans le second, le malloc() l'appel est effectué deux fois, alors que dans le premier, vous passez un pointeur précédemment alloué à realloc() .

Analysons d'abord le premier code. En supposant malloc(0) ne renvoie pas NULL en cas de succès, ptr a une valeur valide. Lorsque vous faites realloc(ptr, 1024) , realloc() vous donne essentiellement un nouveau tampon qui a la taille 1024, et le ptr devient invalide. Une implémentation conforme peut retourner la même adresse que celle déjà dans ptr . Donc, votre if condition peut retourner vrai. (Notez, cependant, en regardant la valeur de ptr après realloc(ptr, 1024) peut être un comportement indéfini.)

Maintenant la question que vous posez :malloc(0) == realloc(malloc(0), 1024) . Dans ce cas, supposons que le malloc(0) sur les retours LHS et RHS non NULL . Ensuite, ils sont garantis différents. Aussi, la valeur de retour de malloc() sur le LHS n'a pas été free() d encore, donc tout autre malloc() , calloc() , ou realloc() peut ne pas renvoyer cette valeur. Cela signifie que si vous avez écrit votre condition comme :

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

vous ne verrez pas possible sur la sortie (sauf si malloc() et realloc() échoue et renvoie 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;
}

Sous OS X, mon code n'a rien produit lorsque je l'ai exécuté. Sous Linux, il imprime possible, OK .


malloc(0) est défini par la mise en œuvre en ce qui concerne C99.

À partir de C99 [Section 7.20.3]

L'ordre et la contiguïté du stockage alloué par les appels successifs aux fonctions calloc, malloc et realloc ne sont pas spécifiés . Le pointeur renvoyé si l'allocation réussit est correctement aligné de sorte qu'il puisse être assigné à un pointeur vers n'importe quel type d'objet, puis utilisé pour accéder à un tel objet ou à un tableau de tels objets dans l'espace alloué (jusqu'à ce que l'espace soit explicitement désalloué). La durée de vie d'un objet alloué s'étend de l'allocation jusqu'à la désallocation. Chacune de ces allocations doit produire un pointeur vers un objet disjoint de tout autre objet. Le pointeur renvoyé pointe sur le début (adresse d'octet la plus basse) de l'espace alloué. Si l'espace ne peut pas être alloué, un pointeur nul est renvoyé. Si la taille de l'espace demandé est zéro, le comportement est défini par l'implémentation :soit un pointeur nul est renvoyé, soit 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.


Dans C89, malloc(0) dépend de l'implémentation - je ne sais pas si C99 a corrigé cela ou non. En C++, en utilisant :

char * p = new char[0];

est bien défini - vous obtenez un pointeur valide et non nul. Bien sûr, vous ne pouvez pas utiliser le pointeur pour accéder à ce qu'il pointe sans invoquer un comportement indéfini.

Quant à savoir pourquoi cela existe, c'est pratique pour certains algorithmes et cela signifie que vous n'avez pas besoin d'encombrer votre code de tests pour les valeurs nulles.


Linux
  1. Que signifie "-" (double tiret) ?

  2. Qu'est-ce que Echo $ ? Faire??

  3. Que fait réellement Libgl_always_indirect=1 ?

  4. Qu'est-ce que . Commande ~/.bashrc Faire ? ?

  5. Que renvoie la commande Ls -al .* ?

Que fait Bamfdaemon ?

Que fait poll() avec un timeout de 0 ?

Quel code d'erreur renvoie un processus renvoyant des erreurs de segmentation ?

Que fait 'bash -c' ?

Que fait init exactement ?

Que produit pwd ?