Vérifier si un pointeur est alloué de la mémoire ou pas
Peut-on vérifier si un pointeur est passé à une fonction est attribuée à la mémoire ou en C?
J'ai wriiten ma propre fonction en C qui accepte un pointeur de caractère - buf [pointeur vers une mémoire tampon] et de la taille - buf_siz [taille de la mémoire tampon]. En fait, avant l'appel de cette fonction, l'utilisateur doit créer une zone tampon et d'allouer de la mémoire d'buf_siz.
Puisqu'il y a une chance que l'utilisateur peut oublier de faire de l'allocation de mémoire et tout simplement passer le pointeur de ma fonction, je veux vérifier ce point. Donc est il possible que je peux vérifier dans ma fonction pour voir si le pointeur est passé est vraiment alloué avec buf_siz quantité de mémoire .. ??
EDIT1: Il semble qu'il n'y est pas de la bibliothèque standard pour le vérifier .. mais est-il sale hack pour le vérifier .. ??
EDIT2: je sais que ma fonction sera utilisée par un bon programmeur en C ... Mais je veux savoir si nous pouvons vérifier ou pas .. si on peut je voudrais l'entendre qu'elle ..
Conclusion: il est Donc impossible de vérifier si un pointeur est alloué à la mémoire ou pas au sein d'une fonction
- Je ne crois pas vraiment, mais je ne me sens pas suffisamment à l'aise pour poster une réponse.
- Il n'y a aucun moyen de vérifier, à moins d'utiliser un gestionnaire de mémoire ou rouler vos propres.
- Si c'est un pointeur de caractère, nous pouvons faire strlen() ou sizeof() et de vérifier la quantité de mémoire allouée(bien sûr, si la chaîne est terminée par NUL). Pour les autres types, je ne suis pas sûr qu'il y en est d'une certaine façon.!!
- Je sais que c'est une vieille question, mais il est possible de garder une trace de la mémoire allouée, sans l'aide de hacks. Mon code ci-dessous donne quelques extraits pour vous mettre en route.
- La conclusion que l'on doit tirer de tout cela est que vous ne devriez pas vérifier, même si c'était possible. Cet article explique le problème. Bien qu'écrit dans Windows terme, le problème n'est pas spécifique à Windows.
Vous devez vous connecter pour publier un commentaire.
Vous ne pouvez pas vérifier, à l'exception de certains de la mise en œuvre spécifique de hacks.
Les pointeurs ont aucune information, autre que celui où ils point. Le meilleur que vous pouvez faire est de dire "je sais comment cette version de compilateur alloue de la mémoire, donc je vais déréférencement de mémoire, déplacez le pointeur de retour de 4 octets, vérifier la taille, permet de s'assurer qu'il correspond à..." et ainsi de suite. Vous ne pouvez pas le faire de manière standard, puisque l'allocation de mémoire est définie par l'implémentation. Ne pas oublier qu'ils pourraient ne pas avoir alloué dynamiquement à tous.
Vous avez juste à assumer votre client sait comment programmer en C. La seule onu-solution je pense, serait d'allouer de la mémoire vous-même et de le retourner, mais ce n'est guère un petit changement. (C'est un grand changement de conception.)
malloc
qui retourne unNULL
pointeur s'il ne parvient pas à allouer la mémoire. Alors ... enmalloc
nous faire confiance?malloc
il serait de retour la valeur NULL si il n'a pas pu allouer de la mémoire. Bien sûr, cela n'empêche pas le client de passer un pointeur qui n'a même pas été utilisé avecmalloc
... jamais l'esprit.Pour une plate-forme spécifique de la solution, vous pouvez être intéressé par la fonction Win32
IsBadReadPtr
(et d'autres). Cette fonction sera capable de (presque) de prédire si vous obtenez une erreur de segmentation lors de la lecture d'une partie de la mémoire.Toutefois, cela ne pas vous protéger dans le cas général, car le système d'exploitation ne sait rien de la C runtime gestionnaire de tas, et si un appelant passe dans un tampon qui n'est pas aussi grand que vous le souhaitez, puis le reste des tas de bloc continuera à être lisible à partir d'un OS de la perspective.
Le code ci-dessous est ce que j'ai utilisé une fois pour vérifier si certains pointeur de la tente de l'accès illégal de la mémoire. Le mécanisme est d'induire un SIGSEGV. Le signal SEGV a été redirigé vers une fonction privée à l'heure, qui utilise longjmp pour revenir au programme. Il est une sorte de hack, mais il fonctionne.
Le code peut être amélioré (utilisation "sigaction" au lieu de "signal", etc), mais c'est juste pour donner une idée. Aussi, il est portable à d'autres versions d'Unix pour Windows je ne suis pas sûr. Notez que le signal SIGSEGV ne doit pas être utilisé de quelque part d'autre dans votre programme.
i = (int*) malloc(1);
. Vous êtes peut-être penser à une autre langue.setjmp()
etlongjmp()
devrait probablement être remplacé parsigsetjmp()
etsiglongjmp()
. Voir stackoverflow.com/questions/20755260/...Une fois, j'ai utilisé un sale hack sur mon 64bit Solaris. En 64 bits mode le tas commence à 0x1 0000 0000. En comparant le pointeur j'ai pu déterminer si c'était un pointeur sur les données ou le segment de code
p < (void*)0x100000000
, un pointeur dans le tasp > (void*)0x100000000
ou un pointeur de mémoire dans une région cartographiée(intptr_t)p < 0
(mmap renvoie les adresses à partir du haut de la zone adressable).Cela a permis à mon programme pour tenir alloué et mappé en mémoire les pointeurs dans la même carte, et avoir ma carte module gratuit le bon pointeurs.
Mais ce genre de truc est très portables et si votre code s'appuie sur quelque chose comme ça, il est temps de repenser l'architecture de votre code. Vous êtes probablement fait quelque chose de mal.
J'ai toujours initialiser les pointeurs à null valeur. Donc quand j'ai allouer de la mémoire, elle va changer. Lorsque je vérifie si la mémoire a été allouée je ne
pointer != NULL
. Quand je désalloue la mémoire j'ai également réglé le pointeur à null. Je ne pense pas de toute façon de savoir si il y avait assez de mémoire allouée.Cela ne résout pas votre problème, mais tu as à faire confiance que si quelqu'un écrit des programmes en C, alors il est assez habile pour le faire droit.
Je sais que c'est une vieille question, mais presque tout est possible en C. Il y a quelques hackish solutions déjà ici, mais un moyen valable de déterminer si la mémoire a été correctement allouée est d'utiliser un oracle pour prendre la place de
malloc
,calloc
,realloc
, etfree
. C'est de la même façon infrastructures de test (comme cmocka) permet de détecter des problèmes de mémoire (seg défauts, pas de libération de la mémoire, etc.). Vous pouvez gérer une liste d'adresses de mémoire allouée qu'ils sont alloués et il suffit de cocher cette liste lorsque l'utilisateur veut utiliser votre fonction. J'ai mis en place quelque chose de très similaire pour mon propre framework de test. Un exemple de code:Vous auriez des fonctions similaires pour
calloc
,realloc
, etfree
, chaque morceau de pâte avec le préfixe__wrap_
. Le réelmalloc
est disponible par le biais de l'utilisation de__real_malloc
(similaire pour les autres fonctions, vous êtes d'emballage). Chaque fois que vous voulez vérifier si la mémoire est allouée, il suffit de parcourir les liésmemory_ref
liste pour rechercher l'adresse de la mémoire. Si vous trouvez qu'il est et il est assez grand, vous savez pour certain l'adresse de la mémoire ne sera pas le plantage de votre programme; sinon, une erreur est renvoyée. Dans le fichier d'en-tête de votre programme, vous devez ajouter ces lignes:Mes besoins sont assez simples, donc j'ai mis en place un très mise en œuvre de base, mais vous pouvez imaginer comment cela pourrait être étendu à avoir un meilleur système de suivi (par exemple, créer un
struct
qui garde une trace de l'emplacement de mémoire en plus de la taille). Ensuite il vous suffit de compiler le code avecL'inconvénient est que l'utilisateur a pour compiler le code source avec les directives ci-dessus; toutefois, il est loin d'être le pire que j'ai vu. Il y a une surcharge pour l'allocation et la libération de la mémoire, mais il y a toujours une surcharge lors de l'ajout de la sécurité.
Non, en général il n'y a aucun moyen de le faire.
En outre, si votre interface est tout simplement "passer un pointeur vers une mémoire tampon où je vais mettre des choses", alors le visiteur peut choisir pas pour allouer de la mémoire à tous, et au lieu d'utiliser une taille fixe de la mémoire tampon qui est allouée statiquement ou une variable automatique ou quelque chose. Ou c'est peut-être un pointeur sur une partie d'un plus grand objet sur le tas.
Si votre interface spécifiquement dit "passez un pointeur vers la mémoire allouée (parce que je vais le désallouer)", alors vous devriez vous attendre que l'appelant le faire. À défaut de le faire n'est pas quelque chose que vous pouvez détecter de manière fiable.
Un hack que vous pouvez essayer de vérifier si votre pointeur de pile de la mémoire allouée.
Ce ne sera pas vous aider, en général, comme la mémoire tampon allouée pourrait être le petit ou le pointeur pointe vers certains de mémoire globale de l'article (.sev, .const, ...).
Pour effectuer ce hack, vous devez d'abord stocker l'adresse de la première variable dans main(). Plus tard, vous pouvez comparer cette adresse avec l'adresse d'une variable locale dans votre routine spécifique.
Toutes les adresses entre les deux adresses sont situés sur la pile.
Vous ne pouvez pas vérifier avec tout ce qui est disponible dans la norme C. Même si votre compilateur spécifique ont été pour fournir une fonction pour le faire, il serait toujours une mauvaise idée. Voici un exemple de pourquoi:
Que tout le monde dit, il n'y a pas un moyen standard pour le faire.
Jusqu'à présent, personne ne l'a mentionné ' L'Écriture De Code Solide " par Steve Maguire. Bien que reprochait dans certains quarts, le livre a des chapitres sur le sujet de la gestion de la mémoire, et explique comment, avec un soin et un contrôle complet sur l'allocation de la mémoire dans le programme, vous pouvez faire ce que vous demandez et de déterminer si un pointeur vous sont donné est valide d'un pointeur vers la mémoire allouée dynamiquement. Cependant, si vous envisagez d'utiliser des bibliothèques tierces, vous trouverez que peu d'entre eux vous permettent de modifier l'allocation de mémoire routines de votre propre, ce qui complique considérablement l'analyse.
Je ne sais pas un moyen de le faire à partir d'un appel de la bibliothèque, mais sur Linux, vous pouvez regarder
/proc/<pid>/numa_maps
. Il montrera toutes les sections de la mémoire et de la troisième colonne va dire "tas" ou "pile". Vous pouvez regarder le raw la valeur du pointeur de voir où il s'aligne.Exemple:
Donc des pointeurs qui sont au-dessus de 0x01167000 mais en dessous de 0x7f39904d2000 sont situés dans le tas.
Non, vous ne pouvez pas. Vous remarquerez qu'aucune des fonctions de la bibliothèque standard, ou n'importe où ailleurs ce faire. C'est parce que il n'y a pas de méthode standard pour le dire. Le code d'appel a juste à accepter la responsabilité de la correcte gestion de la mémoire.
en général lib les utilisateurs sont responsables de l'entrée de vérifier et de vérification. Vous pouvez voir AFFIRMER ou quelque chose dans le répertoire lib de code et qu'ils sont utilisés uniquement pour le débogage perpose. c'est une façon standard lors de l'écriture de C/C++. alors que beaucoup de codeurs comme pour faire ce genre de vérifier et verfying dans leur lib code très soigneusement. vraiment de "MAUVAISES" habitudes. Comme indiqué dans le IOP/IOD, lib interfaces devraient être les contrats et faire clairement ce que sera la lib faire et ce qui va pas, et ce qu'est une lib utilisateur doit faire et ce qui ne devrait pas être nécessaire.
Un pointeur non initialisée est exactement ce que - non initialisée. Elle peut pointer vers quelque chose ou tout simplement avoir une adresse non valide (c'est à dire un pas associé à physique ou de la mémoire virtuelle).
La solution la plus pratique est d'avoir une durée de validité de la signature dans les objets pointés. Créer un malloc() wrapper qui alloue la taille de bloc demandée en plus de la sizeof une signature de la structure, crée une signature de la structure au début du bloc, mais retourne le pointeur à l'emplacement après la signature. Vous pouvez ensuite créer une fonction de validation qui prend le pointeur, utilise un décalage négatif pour obtenir la validité de la structure et le vérifie. Vous aurez bien sûr besoin d'un correspondant free() wrapper pour invalider le bloc en remplacement de la validité de la signature, et à effectuer les gratuit, de la réalité du début du bloc alloué.
En tant que la validité de la structure, vous pouvez utiliser la taille du bloc et de son complément. De cette façon, vous n'avez pas seulement un moyen de valider le bloc (XOR les deux valeurs et de les comparer à zéro), mais vous avez aussi des informations sur la taille de bloc.
Il y a une façon simple de le faire. Chaque fois que vous créez un pointeur, écrire un wrapper autour d'elle. Par exemple, si votre programmeur utilise votre bibliothèque pour créer une structure.
assurez-vous qu'il alloue de la mémoire à l'aide de votre fonction, telle que la
si ce struct_var contient de la mémoire est allouée dynamiquement, par ex,
si la définition de struct_type était
puis dans votre init_struct_type() fonction de cela,
De cette façon,à moins qu'il alloue de la temp->chaîne de valeur, il ne reste NULLE. Vous pouvez vérifier dans les fonctions qui utilisent cette structure, si la chaîne est NULLE ou pas.
Une chose de plus, si le programmeur est tellement mauvais, qu'il ne parvient pas à utiliser vos fonctions, mais plutôt directement les accès non alloué de la mémoire, il ne mérite pas de l'utilisation de votre bibliothèque. Assurez-vous juste que votre documentation spécifie tout.
Vous pouvez en appelant
malloc_size(my_ptr)
dansmalloc/malloc.h
il retourne la taille malloc a consacré à vous pour votre pointeur et 0 si le pointeur n'a pas été alloué. Gardez à l'esprit que malloc redimensionne la taille d'un bloc alloué pour s'assurer que le plus restrictif type de variable peut être déréférencé de pointeur et d'aligner la mémoire. Donc, si vous appelez la fonction malloc(1) (ainsi que malloc(0)) malloc renvoie en fait 16 octets (sur la plupart des machines) parce que le plus restrictif de type a une taille de 16 octetsmalloc_size
existe (ce n'est pas une fonction standard) et 2) que le seul problème est que l'appelant a alloué à peu de mémoire.malloc_size
de ne pas faire quelque chose d'utile si vous lui donnez un pointeur qui n'était pas retourné à partir demalloc
, qui est la situation de l'OP est en train de décrire.Un pointeur tracker, de pistes et de la vérification de la validité d'un pointeur
utilisation:
créer mémoire int * ptr = malloc(sizeof(int) * 10);
ajouter l'adresse de pointeur sur le tracker Ptr(&ptr);
vérifier pour ne pas avoir des pointeurs PtrCheck();
et gratuit tous les traqueurs à la fin de votre code
PtrFree();
Il n'y a presque jamais "jamais" dans les ordinateurs. Croix plate-forme est bien au-dessus prévu. Après 25 ans, j'ai travaillé sur des centaines de projets à l'anticipation de la croix-plate-forme et il ne s'est jamais matérialisée.
Évidemment, une variable sur la pile, serait point dans la zone de la pile, qui est presque linéaire. La croix-plate-forme de ramasseurs d'ordures travail, en marquant le haut ou (bas) de la pile, l'appel d'une petite fonction pour vérifier si la pile grandit vers le haut ou vers le bas, puis en cochant le pointeur de pile, à savoir la taille de la pile est. C'est à votre portée. Je ne sais pas une machine qui n'a pas d'implémenter une pile de cette façon (soit en croissance vers le haut ou vers le bas.)
Il vous suffit de vérifier si l'adresse de notre objet ou le pointeur se trouve entre le haut et le bas de la pile. Voici comment vous pouvez savoir si c'est une pile variable.
Trop simple. Hey, est-il exact c++? Pas de. Est correcte important? En 25 ans, j'ai vu la manière plus de l'estimation de la corriger. Eh bien, disons-le de cette façon: Si vous êtes piratage, vous ne faites pas des vrais programmation, vous êtes probablement juste regurigating quelque chose qui a déjà été fait.
Comment intéressant, c'est que?
malloc
-même les fonctions ne sont pas nécessairement effectuer une action qui vont se retrouver au tas d'expansion. C++ a une façon toute nouvelle de l'allocation de mémoire et tout le monde sait que l'utilisation de la pré-défini les fonctions de C n'est pas une bonne idée.Bien, je ne sais pas si quelqu'un ne l'avait pas mis ici déjà ou si il va être une possibilité dans votre programme. J'ai été aux prises avec les mêmes chose dans mon projet de l'université.
Je l'ai résolu tout simplement - Dans l'initialisation de la partie de main() , après j'ai déclaré
LIST *ptr
, j'ai juste misptr=NULL
. CeAinsi, lorsque l'allocation échoue ou le pointeur de la souris n'est pas attribué à tous, elle sera NULLE. AINSI, vous pouvez simplement le tester avec si.
Je ne sais pas comment votre programme est écrit, mais vous avez sûrement comprendre que suis-je en train d'essayer de mettre en évidence. Si il est possible de vérifier comme ça, ta répartition et de passer ensuite vos arguments à vous fonctionnez, vous pourriez avoir une solution simple.
Bien sûr, vous devez être prudent d'avoir vos fonctions avec l'allocation et de la création de la structure fait du bien, mais où en C, vous n'avez pas à être prudent.