9
votes

Emballage Malloc - C

Je suis un débutant en C. Lorsque vous lisez le code source de Git, j'ai trouvé cette fonction wrapper autour de MALLOC code>.

void *xmalloc(size_t size)
{
    void *ret = malloc(size);
    if (!ret && !size)
        ret = malloc(1);
    if (!ret) {
        release_pack_memory(size, -1);
        ret = malloc(size);
        if (!ret && !size)
            ret = malloc(1);
        if (!ret)
            die("Out of memory, malloc failed");
    }
#ifdef XMALLOC_POISON
    memset(ret, 0xA5, size);
#endif
    return ret;
}


4 commentaires

Bravo pour la lecture du code des programmes complexes existants - je souhaite que plus de développeurs l'ont fait.


Pour la question 2: Sa définition est dans SHA1_FILE.c (C'est la mémoire de faire avec les objets Pack de GIT, vraisemblablement) et son prototype est dans Git-compat-util.h. (Indice: Tant que vous êtes looknig au code source de GIT, utilisez git grep version_pack_memory pour le trouver!)


@Lars: merci. @JEfromi: bon point sur git grep .


"Je suis un débutant en C. Tout en lisant le code source de Git ..." - dans le fond profond, génial.


4 Réponses :


2
votes

pour la question 1:

La norme ne définit pas le comportement de malloc (0) . Cela peut renvoyer un pointeur valide ou peut renvoyer null. Différentes implémentations gérent qui différemment afin que le code redevienne sur malloc (1) pour obtenir un comportement cohérent.

pour la question 3:

Il définit le contenu du tampon à quelque chose de «étrange». De cette façon, votre code espérons que ne s'appuie pas sur le contenu étant quelque chose de spécifique (dont MALLOC ne garantit pas).


4 commentaires

Recommandez-vous d'utiliser ce wrapper?


@Appu - Changer de 0 à 1 et faire le memset va bien. La police de la stratégie OOM dépend de ce que vous écrivez. La politique convient à une utilitaire de ligne de commande qui fait une seule chose et sort. La politique peut être correcte ou non pour un serveur de longue durée (souhaitez-vous quitter le processus ou souhaitez-vous nettoyer la demande actuelle et réessayer). La politique n'est pas acceptable pour une bibliothèque générique car la stratégie sur OOM devrait être décidée par la demande principale.


Bon point. Le code que j'écrirai est pour une bibliothèque. Je pense donc que je devrais éviter matrice .


"Devrait-il renvoyer un pointeur valide qui n'a pas de mémoire qui lui est associé ou devrait-il renvoyer NULL?" - OOH, je peux répondre à ça, "oui" ;-) Je ne sais pas si votre réponse précise que la mise en œuvre doit faire l'une ou l'autre. Et que s'il s'agit d'un pointeur valide, c'est un autre à chaque fois.



3
votes
  1. MALLOC (0) ne fonctionne pas sur toutes les plateformes, auquel cas une allocation d'une octet est faite à la place. Permettant l'attribution des blocs de mémoire de 0-longueur simplifie la logique de niveau supérieur du programme.

  2. Je ne sais pas.

  3. En remplissant la mémoire allouée avec une valeur non nulle, il est plus facile de trouver des bogues dans le programme où la mémoire est utilisée sans initialisation correcte: le programme s'écrasera presque immédiatement dans de tels cas. Comme le remplissage de la mémoire prend du temps, il est enveloppé dans un préprocesseur défini, il est donc compilé en seulement lorsque vous le souhaitez.


1 commentaires

Le comportement de 'Malloc (0)' est défini la mise en œuvre. Il renvoie un pointeur NULL ou un pointeur non nul à zéro octets de données (qui, bien sûr, vous ne pouvez jamais la désarférence). C99 §7.20.3 Fonctions de gestion de la mémoire: "Si la taille de l'espace demandé est nulle, le comportement est défini sur la mise en oeuvre: un pointeur null est renvoyé, ou le comportement est comme si la taille était une valeur non nulle, sauf que le retour le pointeur ne doit pas être utilisé pour accéder à un objet. "



2
votes

Pour la question 2: Livraison_Pack_Memory se trouve dans SHA1_FILE.C: 570 .


0 commentaires

1
votes

Je ne suis pas familier avec ce wrapper mais voici ce que c'est faire

1 - Si Taille = 0 a été spécifiée, il alloue 1 octet à la place si le malloc sous-jacent ne le faisait pas

Ceci est probablement fait de sorte qu'un appelant puisse toujours se libérer sur celui-ci (comme Realloc)

2 Je suppose que c'est d'essayer de forcer le sous-système de mémoire sous-jacent à avoir l'air plus difficile pour la mémoire

3 les forces xmalloc_poison à tamponner à un état connu Ceci est une pratique courante afin d'empêcher et de détecter des bugs impairs causés par des données non initialisées

Deuxièmement, pourquoi voulez-vous envelopper MALLOC. Commencez avec l'idée de ce que vous voulez faire, puis de la mettre en œuvre ou de copier une implémentation. Raisons d'emballage MALLOC

  1. Détection de fuite
  2. Analyse d'utilisation
  3. mise en commun de la mémoire
  4. Débogage (comme le xmalloc_poison)
  5. Vérification forcée

    Presque toutes ces personnes peuvent être faites avec Valgrind - ce qui fait beaucoup plus.

    Le livre "Code Solid" a un bon ensemble d'emballages de mémoire pour 1,4 et 5


2 commentaires

Merci d'avoir répondu. Honnêtement, je suis un peu perdu dans le monde C. Donc, pour éviter de faire des erreurs, je lis d'autres programmes de programmes et découvrez comment ils écrivent du code.


"Ceci est probablement fait de sorte qu'un appelant puisse toujours se libérer dessus" - vous pouvez toujours appeler gratuitement ou realloc sur un pointeur NULL. Je ne connais pas la source de Git, mais il est plus probable que cela soit fait pour vous assurer que un retour de 0 peut être traité définitivement par l'appelant comme une erreur, même si l'entrée était de 0. ou éventuellement de s'assurer que les pointeurs de 0- Les allocations de taille sont comparatives différentes ("Ce n'est pas votre tampon de taille zéro, de sorte que cela ne doit pas être votre valise!").