web-dev-qa-db-fra.com

quel est le point de malloc (0)?

Je viens de voir ceci code:

artist = (char *) malloc(0);

et je me demandais pourquoi on ferait ça?

106
jldupont

Selon les spécifications, malloc (0) retournera "un pointeur null ou un pointeur unique pouvant être passé avec succès à free ()".

Cela vous permet essentiellement de ne rien allouer, tout en passant la variable "artist" à un appel à free () sans souci. Pour des raisons pratiques, c'est à peu près la même chose que faire:

artist = NULL;
109
Reed Copsey

La norme C (C17 7.22.3/1) dit:

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

Ainsi, malloc(0) peut renvoyer NULL ou un pointeur valide qui ne peut pas être déréférencé . Dans les deux cas, il est parfaitement correct d'appeler free().

Je ne pense pas vraiment que malloc(0) soit très utile, sauf dans les cas où malloc(n) est appelé dans une boucle, par exemple, et n peut être nul.

En regardant le code dans le lien, je pense que l'auteur avait deux idées fausses:

  • malloc(0) renvoie un pointeur valide toujours , et
  • free(0) est mauvais.

Il s’est donc assuré que artist et les autres variables avaient toujours une valeur "valide". Le commentaire en dit autant: // these must always point at malloc'd data.

46
Alok Singhal

le comportement de malloc (0) est spécifique à la mise en œuvre. La bibliothèque peut renvoyer NULL ou avoir le comportement malloc habituel, sans mémoire allouée. Quoi qu'il en soit, il doit être documenté quelque part.

Généralement, il renvoie un pointeur valide et unique, mais ne doit PAS être déréférencé. Notez également qu'il PEUT consommer de la mémoire même s'il n'a rien alloué.

Il est possible de réaffecter un pointeur malloc (0) non nul.

Avoir un malloc (0) verbatim n’est pas très utile cependant. Il est surtout utilisé lorsqu'une allocation dynamique est égale à zéro octet et que vous ne voulez pas la valider.

9
Coincoin

Une réponse ailleurs sur cette page commence par «malloc (0) renvoie une adresse mémoire valide et dont la plage dépend du type de pointeur auquel la mémoire est allouée». Cette déclaration est incorrecte (je n'ai pas assez de réputation pour commenter cette réponse directement, je ne peux donc pas mettre ce commentaire directement sous).

Faire malloc (0) va pas allouer automatiquement de la mémoire de taille correcte. La fonction malloc ignore ce sur quoi vous projetez le résultat. La fonction malloc repose uniquement sur le numéro de taille que vous donnez comme argument. Vous devez faire malloc (sizeof (int)) pour obtenir suffisamment de stockage pour contenir un int, par exemple, pas 0.

4
Krellan

malloc(0) n'a aucun sens pour moi, sauf si le code s'appuie sur un comportement spécifique à la mise en œuvre. Si le code est censé être portable, il doit alors tenir compte du fait qu'un retour NULL de malloc(0) n'est pas un échec. Alors, pourquoi ne pas simplement assigner NULL à artist de toute façon, puisque c'est un résultat valide, qui contient moins de code, et qui ne fera pas perdre du temps à vos programmeurs de maintenance?

malloc(SOME_CONSTANT_THAT_MIGHT_BE_ZERO) ou malloc(some_variable_which_might_be_zero) pourraient peut-être être utilisés, mais vous devez également faire très attention à ne pas traiter une déclaration NULL comme un échec si la valeur est 0, mais une taille 0 est supposée être OK.

3
Steve Jessop

Il y a beaucoup de demi-réponses vraies ici, alors voici les faits. La page de manuel de malloc() dit:

Si size est 0, alors malloc () renvoie NULL ou une valeur de pointeur unique pouvant ultérieurement être passé avec succès à free ().

Cela signifie que rien ne garantit que le résultat de malloc(0) soit unique ou non NULL. La seule garantie est fournie par la définition de free(). Encore une fois, voici ce que dit la page de manuel:

Si ptr est NULL, aucune opération n'est effectuée.

Ainsi, quel que soit le retour de malloc(0), il peut être passé en toute sécurité à free(). Mais il en va de même pour un pointeur NULL.

En conséquence, écrire artist = malloc(0); n'est en aucun cas meilleur que d'écrire artist = NULL;

3
cmaster

Certes, je n'ai jamais vu cela auparavant, c'est la première fois que je vois cette syntaxe, pourrait-on dire, un cas classique de surdose de fonction. En conjonction avec la réponse de Reed, je voudrais souligner qu’il existe une chose similaire, qui apparaît comme une fonction surchargée realloc:

  • toto est non-NULL et la taille est égale à zéro, realloc(foo, size);. Lorsque vous passez un pointeur non NULL et une taille de zéro à realloc, realloc se comporte comme si vous aviez appelé free (…)
  • foo est NULL et sa taille est différente de zéro et supérieure à 1, realloc(foo, size);. Lorsque vous passez un pointeur NULL et que la taille est différente de zéro, realloc se comporte comme si vous aviez appelé malloc (…)

J'espère que cela vous aidera, Cordialement, Tom.

2
t0mm13b

Pourquoi tu ne devrais pas faire ça ...

Puisque la valeur de retour de malloc dépend de la mise en œuvre, vous pouvez obtenir un pointeur NULL ou une autre adresse. Cela peut entraîner des débordements de mémoire tampon si le code de gestion des erreurs ne vérifie pas la taille ni la valeur renvoyée, ce qui entraîne des problèmes de stabilité (plantages), voire des problèmes de sécurité plus graves.

Prenons cet exemple, où un accès ultérieur à la mémoire via l'adresse renvoyée endommagera la taille de tas siff et que l'implémentation renvoie une valeur non NULL.

size_t size;

/* Initialize size, possibly by user-controlled input */

int *list = (int *)malloc(size);
if (list == NULL) {
  /* Handle allocation error */
}
else {
  /* Continue processing list */
}

Voir cette page de codage sécurisé des normes de codage CERT où j'ai pris l'exemple ci-dessus pour une lecture plus approfondie.

2
auselen

Pour répondre réellement à la question posée: il n’ya aucune raison de le faire

1
Paolo

Sous Windows:

  • void *p = malloc(0); allouera un tampon de longueur nulle sur le tas local. Le pointeur renvoyé est un pointeur de segment de mémoire valide.
  • malloc appelle finalement HeapAlloc en utilisant le tas d'exécution C par défaut qui appelle ensuite RtlAllocateHeap, etc.
  • free(p); utilise HeapFree pour libérer le tampon de longueur 0 sur le tas. Ne pas le libérer entraînerait une fuite de mémoire.
0
sam msft

malloc (0) retournera NULL ou un pointeur valide qui peut être passé à juste titre à free. Et bien qu'il semble que la mémoire sur laquelle elle pointe soit inutile ou qu'il ne puisse pas être écrit ou lu, ce n'est pas toujours vrai. :)

int *i = malloc(0);
*i = 100;
printf("%d", *i);

Nous nous attendons à une faute de segmentation ici, mais étonnamment, cela affiche 100! C'est parce que malloc demande en réalité une énorme quantité de mémoire lorsque nous appelons malloc pour la première fois. Chaque appel à malloc après cela utilise la mémoire de ce gros morceau. Une fois que cet énorme bloc est terminé, une nouvelle mémoire est demandée.

Utilisation de malloc (0): si vous souhaitez que les appels Malloc suivants soient plus rapides, appeler malloc (0) doit le faire pour vous (sauf dans les cas Edge).

0
Sagar Bhosale

C'est en fait très utile, et (évidemment à mon humble avis), le comportement autorisé de retourner un pointeur NULL est cassé. Un pointeur dynamique est utile non seulement pour ce qu'il pointe, mais aussi pour le fait que son adresse est unique. Le renvoi de NULL supprime cette deuxième propriété. Tous les mallocs intégrés que je programme (assez souvent en fait) ont ce comportement.

0
Scott Franco