Comment obtenir la taille d'un bloc de mémoire alloué à l'aide de malloc ()? [dupliquer]

StackOverflow https://stackoverflow.com/questions/1208644

Question

  

Doublons possibles:
   Comment puis-je obtenir la taille d'un tableau à partir d'un pointeur en C?
   Si aucun moyen de déterminer la taille d'un tableau C ++ par programme? Et si non, pourquoi?

Je reçois un pointeur sur une partie de la mémoire allouée à partir d'une fonction de style C. Maintenant, il serait vraiment intéressant pour le débogage de savoir comment gros le bloc de mémoire alloué que ce pointeur pointe est.

Y a-t-il quelque chose de plus élégant que de provoquer une exception en dépassant aveuglément ses frontières?

Merci d'avance, Andreas

EDIT:

J'utilise VC ++ 2005 sous Windows et GCC 4.3 sous Linux

EDIT2:

J'ai _msize sous VC ++ 2005 Malheureusement, il en résulte une exception en mode débogage ....

EDIT3:

Bien. J'ai essayé la façon que j'ai décrite ci-dessus à l'exception, et cela fonctionne. Au moins pendant que je débogue et veille à ce que immédiatement après l'appel à la sortie de la bibliothèque je cours sur les limites du tampon. Fonctionne comme un charme.

Cela n’est tout simplement pas élégant et n’est en aucun cas utilisable dans le code de production.

Était-ce utile?

La solution

Ce n'est pas standard, mais si votre bibliothèque a une fonction msize () qui vous donnera la taille.

Une solution courante consiste à envelopper malloc avec votre propre fonction qui enregistre chaque demande avec la taille et la plage de mémoire résultante. Dans la version de publication, vous pouvez revenir au réel. malloc .

Autres conseils

Si vous ne craignez pas la violence sournoise pour le débogage, vous pouvez # définir des macros pour raccrocher les appels à malloc et les libérer, et compléter les 4 premiers octets avec la taille.

Au rythme de

void *malloc_hook(size_t size) {
    size += sizeof (size_t);
    void *ptr = malloc(size);
    *(size_t *) ptr = size;
    return ((size_t *) ptr) + 1;
}

void free_hook (void *ptr) {
    ptr = (void *) (((size_t *) ptr) - 1);
    free(ptr);
}

size_t report_size(ptr) {
    return * (((size_t *) ptr) - 1);
}

puis

#define malloc(x) malloc_hook(x)

et ainsi de suite

La bibliothèque d'exécution C ne fournit pas une telle fonction. De plus, provoquer délibérément une exception ne vous dira pas non plus quelle est la taille du bloc.

Généralement, ce problème est résolu en C en conservant une variable distincte qui garde la trace de la taille du bloc alloué. Bien sûr, cela est parfois gênant, mais il n’ya généralement aucun autre moyen de le savoir.

Votre bibliothèque d'exécution C peut fournir des fonctions de débogage de tas pouvant interroger des blocs alloués (après tout, free () doit savoir quelle est la taille du bloc), mais tout ce genre de chose sera non portable.

Avec gcc et le éditeur de liens GNU , vous pouvez facilement encapsuler malloc

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


void* __real_malloc(size_t sz);
void* __wrap_malloc(size_t sz)
{
    void *ptr;

    ptr = __real_malloc(sz);
    fprintf(stderr, "malloc of size %d yields pointer %p\n", sz, ptr);

    /* if you wish to save the pointer and the size to a data structure, 
       then remember to add wrap code for calloc, realloc and free */

    return ptr;
}

int main()
{
    char *x;
    x = malloc(103);

    return 0;
}

et compiler avec

gcc a.c -o a -Wall -Werror -Wl,--wrap=malloc

(Bien entendu, cela fonctionnera également avec le code c ++ compilé avec g ++, et avec le nouvel opérateur (via son nom mutilé) si vous le souhaitez.)

En fait, la bibliothèque chargée de manière statique / dynamique utilisera également votre __ wrap_malloc .

Non, et vous ne pouvez pas vous fier à une exception pour dépasser ses limites, à moins que ce ne soit dans la documentation de votre implémentation. Cela fait partie des choses que vous n'avez vraiment pas besoin de savoir pour écrire des programmes. Fouillez dans la documentation de votre compilateur ou dans le code source si vous voulez vraiment savoir.

Il n’existe pas de fonction C standard pour le faire. En fonction de votre plate-forme, il peut y avoir une méthode non portable: quelle bibliothèque OS et C utilisez-vous?

Notez que provoquer une exception n’est pas fiable: il peut y avoir d’autres allocations immédiatement après le morceau que vous avez, et vous risquez de ne recevoir une exception que longtemps après avoir dépassé les limites de votre morceau actuel.

Des vérificateurs de mémoire tels que la vérification de mémoire de Valgrind et Le TCMalloc de Google (la partie vérificateur de tas) conserve la trace de ce genre de choses.

Vous pouvez utiliser TCMalloc pour vider un profil de segment de mémoire indiquant où les éléments ont été alloués, ou simplement le vérifier pour vous assurer que votre segment de mémoire est identique à deux moments de l'exécution du programme à l'aide de SameHeap () .

Solution partielle: sous Windows, vous pouvez utiliser PageHeap pour capturer un accès à la mémoire en dehors du bloc alloué.

PageHeap est un autre gestionnaire de mémoire présent dans le noyau Windows (dans les variantes NT mais personne ne devrait utiliser une autre version de nos jours). Il prend chaque allocation d'un processus et retourne un bloc de mémoire dont la fin est alignée sur la fin d'une page de mémoire, puis rend la page suivante inaccessible (pas de lecture, pas d'accès en écriture). Si le programme tente de lire ou d’écrire après la fin du bloc, vous obtiendrez une violation d’accès que vous pourrez détecter avec votre débogueur préféré.

Comment l'obtenir: Téléchargez et installez le paquet Debugging Tools for Windows de Microsoft: http://www.microsoft.com/whdc/devtools/debugging/default.mspx

Lancez l’utilitaire GFlags, accédez au troisième onglet et entrez le nom de votre exécutable, puis appuyez sur la touche. Cochez la case PageHeap, cliquez sur OK et vous êtes prêt à partir.

La dernière chose à faire: lorsque vous avez terminé le débogage, n'oubliez pas de relancer GFlags et de désactiver PageHeap pour l'application. GFlags entre ce paramètre dans le registre (sous Options d'exécution du fichier HKLM \ Software \ Microsoft \ Windows NT \ CurrentVersion \ Image \), de sorte qu'il est persistant, même après un redémarrage.

Sachez également que l'utilisation de PageHeap peut considérablement augmenter les besoins en mémoire de votre application.

Pour faire ce que vous voulez, vous devez ÊTRE l'allocateur. Si vous filtrez toutes les demandes, puis les enregistrez à des fins de débogage, vous pourrez alors savoir ce que vous voulez lorsque la mémoire est libre.

De plus, vous pouvez vérifier à la fin du programme si tous les blocs alloués ont été libérés et, dans le cas contraire, les lister. Une bibliothèque ambitieuse de ce type pourrait même prendre les paramètres FUNCTION et LINE via une macro pour vous permettre de savoir exactement où vous perdez de la mémoire.

Enfin, MSVCRT de Microsoft fournit un segment de mémoire débogable qui contient de nombreux outils utiles que vous pouvez utiliser dans votre version de débogage pour rechercher des problèmes de mémoire: http://msdn.microsoft.com/en-us/library/bebs9zyz.aspx

Sous Linux, vous pouvez utiliser valgrind pour rechercher de nombreuses erreurs. http://valgrind.org/

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