Comment vérifier si un pointeur est déjà libéré en C?

je voudrais vérifier si un pointeur est libérée déjà ou pas. Comment puis-je utiliser le jeu de compilateurs gnu?

22
demandé sur Raedwald 2011-11-28 22:59:59

6 réponses

vous ne pouvez pas. La façon de suivre ceci serait d'assigner le pointeur à 0 ou NULL après l'avoir libéré. Cependant, comme Fred Larson l'a mentionné, cela ne fait rien à d'autres pointeurs pointant vers le même endroit.

int* ptr = (int*)malloc(sizeof(int));
free(ptr);
ptr = NULL;
22
répondu Chad 2011-11-28 20:23:50

vous ne pouvez pas. Il suffit de lui assigner NULL après free pour s'assurer que vous ne le libérez pas deux fois (c'est ok à free(NULL) ).

mieux encore, si possible n'écrivez pas de code où vous "oubliez" que vous l'avez déjà libéré.

EDIT

interpréter la question comme comment savoir si la mémoire pointée par un pointeur est déjà libérée : vous ne pouvez pas le faire. Que vous avez à faire votre propre comptabilité.

21
répondu cnicutar 2011-11-28 19:01:21

il n'y a aucun moyen fiable de dire si un pointeur a été libéré, comme Greg l'a commenté, la mémoire libérée pourrait être occupée par d'autres données non pertinentes et vous obtiendrez un mauvais résultat.

et en effet il n'y a pas de moyen standard pour vérifier si un pointeur est libéré. qui dit , glibc a des fonctions ( mcheck , mprobe ) pour trouver le statut malloc d'un pointeur pour vérification de cohérence de tas , et l'un d'eux est pour voir si un pointeur est libéré.

cependant , ces fonctions sont principalement utilisées pour le débogage seulement, et ils ne sont pas thread-safe . Si vous n'êtes pas sûr de l'exigence, d'éviter ces fonctions. assurez-vous que vous avez pairé malloc / free .


exemple http://ideone.com/MDJkj :

#include <stdio.h>
#include <stdlib.h>
#include <mcheck.h>

void no_op(enum mcheck_status status) {}

int main()
{
    mcheck(&no_op);

    void* f = malloc(4);

    printf("%d (should be %d)\n", mprobe(f), MCHECK_OK);
    printf("%d (should be %d)\n", mprobe(f), MCHECK_OK);

    free(f);

    printf("%d (should be %d)\n", mprobe(f), MCHECK_FREE);
    printf("%d (should be %d)\n", mprobe(f), MCHECK_FREE);

    return 0;
}
14
répondu kennytm 2017-05-23 11:54:40

vous pouvez étendre le concept d'assigner NULL à la valeur du pointeur en écrivant une macro qui le fait pour vous. Par exemple:

#define FREE(ptr) do{ \
    free((ptr));      \
    (ptr) = NULL;     \
  }while(0)

aussi longtemps que vous vous assurez que votre code n'utilise que FREE() et non free(), Vous pouvez être assez sûr que le code que vous avez écrit ne libère pas la même mémoire deux fois. Bien sûr, cela ne fait rien pour empêcher les appels multiples dans les fonctions de bibliothèque qui libèrent la mémoire. Et il ne fait rien pour garantir qu'Il ya un gratuit pour chaque la fonction malloc.

vous pouvez essayer cela avec une fonction, mais il obtient akward parce que vous devez jeter dans un opérateur de référence et il ne ressemble plus à un appel normal à free ().

4
répondu Brian McFarland 2011-11-28 22:44:26

vous ne le faites pas, puisque vous ne pouvez pas.

gardez la trace des pointeurs que vous obtenez de malloc() et ne libérez ceux-ci, et une seule fois.

si vous voulez, la mémoire n'a pas de mémoire, donc elle ne sait pas si elle est attribuée ou non. Seul le gestionnaire de mémoire de votre système D'exploitation peut vous le dire (mais C n'inclut aucun mécanisme standardisé pour interroger cette information).

2
répondu Kerrek SB 2011-11-28 19:01:26

je sais que cette réponse est a little bit en retard, mais je viens de lire cette réponse et a écrit un certain code à vérifier ce qui suit:

Libre volonté de mettre le bloc de mémoire dans son propre bloc libre liste . Normalement, il essaie aussi de souder des blocs adjacents dans l'espace d'adresse. La liste des blocs libres n'est qu'une liste circulaire de morceaux de mémoire qui ont bien sûr des données admin au début. Le libre-liste est également le premier emplacement , malloc cherche un nouveau morceau de mémoire lorsque nécessaire. il est scanné avant qu'il ne demande une nouvelle mémoire à partir de L'OS . Lorsqu'un bloc est trouvé qui est plus grande que la mémoire nécessaire, il est simplement divisé en deux parties. On est retourné à l'appelant, l'autre est remis dans la liste libre.

ce code ne vérifie que si le premier pointeur attribué est libéré:

int is_freed(void *p)
{
    void * q;
    char p_addr [50];
    char q_addr [50];

    sprintf(p_addr, "%p", p);

    q = malloc (1);
    sprintf(q_addr, "%p", q);
    free (q);

    return ! strcmp(q_addr, p_addr);
}

j'ai testé ce code sur HP-UX et Linux Redhat et il fonctionne, pour le cas d'un seul pointeur.

2
répondu Mansuro 2017-05-23 11:54:40