Question

    

Cette question a déjà une réponse ici:

    
            
  •              quel est le point malloc (0)?                                      17 réponses                          
  •     
    

Qu'est-ce que retourne malloc(0)? La réponse serait-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;
}

Sortie de gcc Linux:

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

La sortie à chaque fois pour continuer à changer malloc(0). Est-ce une réponse standard? Et pourquoi quelqu'un serait intéressé à obtenir un pointeur, autre que la recherche universitaire?

EDIT:

Si malloc(0) renvoie un pointeur factice, alors comment ne fonctionne suivant:

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

EDIT:

Le code suivant renvoie « possible » pour chaque itération. Pourquoi devrait-il pas l'échec?

#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;
}
Était-ce utile?

La solution

D'autres ont répondu à la façon dont fonctionne malloc(0). Je vais répondre à l'une des questions que vous avez posées qui n'a pas encore reçu de réponse (je pense). La question est sur le point realloc(malloc(0), 0):

  

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

La norme dit ceci au sujet 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 par ptr et renvoie un pointeur vers un nouveau tampon alloué. Mais si size est 0, C89 dit que l'effet est équivalent à free(ptr). Fait intéressant, je ne trouve pas cette déclaration dans le projet de C99 (ou n1256 n1336). En C89, la seule valeur raisonnable pour revenir dans ce cas serait NULL.

Alors, il y a deux cas:

  • retourne malloc(0) NULL sur une mise en œuvre. Ensuite, votre appel realloc() est équivalent à realloc(NULL, 0). Cela équivaut à malloc(0) d'en haut (et qui est NULL dans ce cas).
  • malloc(0) retourne non NULL. Ensuite, l'appel est équivalent à free(malloc(0)). Dans ce cas, malloc(0) et realloc(malloc(0), 0) sont pas équivalent.

Notez qu'il ya un cas intéressant: dans le second cas, lorsque malloc(0) retourne non NULL en cas de succès, il peut encore revenir NULL pour indiquer l'échec. Cela se traduira par un appel comme:. realloc(NULL, 0), ce qui équivaudrait à malloc(0), qui peut ou ne peut pas revenir NULL

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

Modifier : Je pense que je comprends ce que votre confusion est:

Regardons un extrait de votre code exemple:

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

Le ci-dessus ne sont pas les mêmes que malloc(0) == realloc(malloc(0), 1024). Dans le second, l'appel malloc() est fait deux fois, alors que dans le premier, vous passez un pointeur précédemment alloué à realloc().

Analysons le premier code d'abord. En supposant malloc(0) ne retourne pas NULL sur la réussite, ptr a une valeur valide. Lorsque vous faites realloc(ptr, 1024), realloc() vous donne essentiellement un nouveau tampon qui a la taille 1024, et la ptr devient invalide. Une mise en œuvre conforme peut retourner la même adresse que celle déjà ptr. Donc, votre état de if peut retourner vrai. (Notez, cependant, 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 retourne non NULL. Ensuite, ils sont garantis différents. En outre, la valeur de retour de malloc() sur le LHS n'a pas été free()d encore, de sorte que toute autre malloc(), calloc() ou realloc() ne peut retourner cette valeur. Cela signifie que si vous avez écrit votre condition:

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

vous ne verrez pas possible sur la sortie (à moins que malloc() et realloc() échouent et renvoient 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 rien affiché quand je l'ai couru. Sous Linux, il imprime possible, OK.

Autres conseils

malloc(0) est Mise en œuvre Defined en ce qui concerne C99.

De C99 [Section 7.20.3]

  

L'ordre et la contiguïté de stockage alloué par les appels successifs à la calloc,   malloc et fonctions realloc est fi ée eci . Le pointeur retourné si l'allocation   succède est convenablement aligné de sorte qu'il peut être affecté à un pointeur sur tout type d'objet   et ensuite utilisé pour accéder à un tel objet ou un ensemble de tels objets dans l'espace alloué   (Jusqu'à ce que l'espace est explicitement désallouée). La durée de vie d'un objet alloué étend   de l'allocation jusqu'à ce que la désaffectation. Chaque telle attribution doit donner un pointeur sur un   objet disjoint de tout autre objet. Le pointeur est retourné des points au début (octet le plus bas   adresse) de l'espace alloué. Si l'espace ne peut être alloué, un pointeur NULL est   revenu. Si la taille de l'espace est zéro, le comportement est l'implémentation   dé fi nies : soit un pointeur NULL est renvoyé, ou le comportement est comme si la taille était un peu   valeur non nulle, sauf que le pointeur retourné ne doit pas être utilisé pour accéder à un objet.

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

char * p = new char[0];

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

Quant à savoir pourquoi il existe, il est commode pour certains algorithmes, et signifie que vous n'avez pas besoin de litière de votre code avec des tests pour des valeurs nulles.

norme C99

  

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

Le comp.lang.c FAQ a suivante pour dire:

  

La norme ANSI / ISO dit qu'il peut   soit faire; le comportement est   la mise en œuvre défini (voir la question   11,33). Code Portable doit soit prendre soin de ne pas appeler malloc (0), ou être   préparé pour la possibilité d'une valeur nulle   retour.

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

Voir C99, section 7.20.3:

  

Si la taille de l'espace requis est   zéro, le comportement est   implementationdefined: soit une valeur nulle   pointeur est retourné, ou le comportement   est comme si la taille était un peu différent de zéro   valeur, sauf que le retour   pointeur ne doit pas être utilisé pour accéder à un   objet.

Ceci est valable pour les trois fonctions d'allocation (c.-à-calloc(), malloc() et realloc()).

Un point personne ne se souciait de parler encore, dans votre premier programme est que realloc longueur 0 est la même chose que free.

à partir de la page de manuel Solaris:

  

La fonction realloc() modifie la taille du bloc a        par ptr à size octets et renvoie un pointeur vers le bloc (éventuellement déplacé). Le contenu ne changera pas jusqu'à la        moindre des nouvelles et anciennes tailles. Si ptr est NULL, realloc()        se comporte comme malloc() de la taille spécifiée. Si size est 0        et ptr est pas un pointeur NULL, l'espace pointé est fait        disponible pour plus d'allocation par l'application, bien que        pas retourné au système. La mémoire est renvoyée au système        seulement à la fin de l'application.

Si on ne sait pas qu'il peut être une source de mauvaise surprise (qui est arrivé à moi).

Je pense que cela dépend. J'ai vérifié les sources visuelles Studio 2005 et a vu cela dans la fonction _heap_alloc:

if (size == 0)
    size = 1;

Je pense que dans de nombreux cas, vous voudrez peut-être un pointeur valide, même lorsque vous demandez zéro octets. En effet, ce comportement cohérent facilite de vérifier vos pointeurs parce que: si vous avez un pointeur non NULL il est OK; si vous avez un pointeur NULL vous avez probablement un problème. Voilà pourquoi je pense que la plupart des implémentations renvoient un pointeur valide, même lorsque vous demandez zéro octets.

  

Si malloc (0) renvoie un pointeur factice, alors comment ne fonctionne suivant:

     

void *ptr = malloc(0);

     

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

Je ne sais pas ce que vous entendez par « pointeur factice ». Si malloc(0) renvoie une valeur non NULL, alors ptr est un pointeur valide à un bloc de mémoire de taille zéro. La mise en œuvre de malloc enregistre ces informations d'une manière spécifique à la mise en œuvre. realloc connaît le chemin (spécifique à la mise en œuvre) pour savoir que les points de ptr à un bloc de mémoire de taille zéro.

(Comment malloc / realloc / free Une possibilité est d'allouer 4 octets de plus que demandé et stocker la taille faire est spécifique à la mise en œuvre. Juste avant le bloc de mémoire. Dans ce cas, ((int *)ptr)[-1] donnerait la taille du bloc de mémoire, qui est 0. Vous ne devriez jamais faire cela à partir de votre code, il est seulement pour une utilisation par realloc et free).

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top