2009-08-03 14 views
3

Il y a probablement une réponse très simple à cela mais je ne peux pas le voir.Comment obtenir une adresse en C?

#include <stdio.h> 

int main(void) { 
int x = 0; 
printf("\n%d\n%d\n",x,&x); 
} 

Bon, alors le printf donne 0 (x) et 2.293.752 (& x). J'essaie de trouver un moyen de regarder n'importe quelle adresse (&) et voir ce qui est déjà stocké là. C'est juste pour l'expérimentation. De l'aide?

+0

Je vous suggère% p au lieu de% d. cela vous donne l'adresse hexadécimale. –

+1

% p est pour 'void *', donc un cast sera nécessaire. BTW la norme ne garantit pas qu'il sera imprimé en hexadécimal. –

+0

Non, mais je n'ai pas encore trébuché sur une implémentation qui ne l'a pas fait. Bien sûr, un compilateur PDP-11 C natif moderne choisirait probablement octal puisque c'était la représentation naturelle pour tout sur un PDP-11. Le dernier compilateur C natif pour le PDP que j'ai utilisé (DECUS C) est trop ancien pour avoir% p, cependant. – RBerteig

Répondre

4
void* memAddr = (void*)0xAABBCCDD; //put your memory address here 
printf("int value at memory address %p is %i", memAddr, *((int*)memAddr)); 

Vous aurez probablement trouver que l'examen des adresses de mémoire arbitraires causera juste un accident.

+0

Testé, et oui, il se bloque juste. Je n'avais pas * vraiment * besoin de savoir ce qui se passait, j'étais juste curieux. – akway

+0

Vous faites l'hypothèse que memAddr contient un int, qui est de 4 octets. Vous devriez au moins utiliser ints non signés, puisque vous êtes également susceptibles de le faire apparaître négatif. Un char converti en un format lisible tel que hex est plus raisonnable. – groundhog

+1

L'adresse peut contenir n'importe quoi et être convertie en n'importe quoi. Par exemple: Vous faites l'hypothèse que memAddr contient un char non signé, qui est un octet. Vous devriez au moins utiliser des caractères signés, car il peut s'agir d'un nombre négatif. Un int converti en un format lisible tel que décimal est plus raisonnable. –

2

Ce serait le déréférencement de pointeur, qui est l'opérateur *. Cependant, vous n'avez aucun moyen de dire ce que le type des données stockées est pour une adresse aléatoire.

#include <stdio.h> 

int main(void) { 
int x = 0; 
printf("\n%d\n%d\n%d\n",x,&x,*(&x)); 
} 

/* resulting output will be 0, some memory address, and 0 again */ 
+0

Pas ce que je voulais dire. Si 2293752 est l'adresse de x, alors je veux vérifier ce qui est à l'adresse 0000000..99999999. – akway

+1

Notez que * (& x) applique réellement l'opérateur * à la valeur (& x). Vous pouvez l'appliquer à quelque chose qui n'implique pas l'opérateur & - par exemple, une adresse constante. – Amber

+1

Vous pouvez constater que GCC interrompt le programme lors de l'exécution. C'est très strict dans ces cas-là, donc vous feriez mieux d'utiliser le bon '% p' et de le lancer dans' void * 'en premier. –

0

En supposant que vous voulez examiner les données « brutes » et que vous connaissez une adresse à l'intérieur de l'espace d'adressage de votre processus, vous feriez ceci:

long x=<address> 
printf("%x", *(int *)x); 
+0

Pourriez-vous expliquer cette partie: * (int *) x – akway

+1

-1: les entiers et les pointeurs sont vraiment des types différents dans C: AFAIK il n'y a aucune garantie que 'long' peut contenir une adresse, et je pense qu'il est beaucoup plus explicite d'utiliser un pointeur, de toute façon. –

+0

Bastien: touché. En effet, ce morceau de code dépend beaucoup du matériel. Il n'y a pas vraiment un moyen portable (et sûr/sécurisé) de faire ce que veut l'affiche originale. akway: * (int *) x projette la variable x comme un pointeur vers un entier, puis récupère la valeur (entière) stockée à l'emplacement pointé par ce pointeur. Il traite efficacement la valeur de x comme une adresse de mémoire pointant vers un entier et lit cet entier. Il échouera (d'une manière dépendante de l'environnement) si cette adresse est en dehors de l'espace d'adressage du processus. – Wilson

1

Si vous voulez explorer la mémoire, je vous recommande d'utiliser un débogueur de bas niveau tel que OllyDbg.

2

Il y a beaucoup de problèmes à essayer de faire ceci, tout d'abord, comme mentionné par Wilson, vous n'aurez vraiment aucune idée de ce qui y est stocké. Wilson est légèrement éteint, cependant, vous devriez vraiment le transformer en un char au lieu d'un int, comme avec un int, vous verrez 4 octets pas un seul octet comme vous le feriez avec un char. En outre, à moins que vous ne puissiez lire les caractères ASCII 8 bits et les mapper à quelque chose de significatif dans votre tête, vous voudrez probablement le convertir à une autre forme comme base2, base8 ou base16.

Vous pouvez le faire de plusieurs façons - probablement la meilleure façon de le faire est avec les opérateurs bit à bit et les opérateurs de décalage binaire, recherchant dans une table de répartition pour le mapper en ASCII visible.

Cependant, vous ne saurez toujours pas ce qui y est stocké, vous pourrez simplement voir une forme codée des données binaires brutes. La raison en est que C n'est typé que par rapport à la variable pointant vers cette adresse mémoire. Une vue nue dans cette mémoire vous donnera seulement binaire et aucune capacité de rechercher quelles variables sont liées à la mémoire ou de quel type sont ces variables.

Un deuxième problème est que vous devez faire attention à ne regarder que dans certaines parties de la mémoire à laquelle vous avez accès. À moins de faire attention à la façon dont vous y accédez, vous ne pouvez pas examiner les segments de code de la mémoire. Vous aurez de la chance si vous fouillez pour éviter une erreur de segmentation.

Toutefois, la manière la plus efficace de vérifier la mémoire d'un processus consiste probablement à vider son segment sur le disque. Dans UNIX, cela se fait via un vidage de base. Vous pouvez ensuite le charger dans un débogueur et explorer le contenu de votre cœur, et même le mapper pour corriger les types avec une connaissance suffisante de la pile. Vous pouvez également utiliser un éditeur binaire pour l'examiner de manière non typée - souvent les chaînes sont reconnaissables.

Bonne chance!

0

pour voir une adresse que vous pouvez utiliser% p

printf("%p",&x); 

Je vous recommande de commencer à lire sur les pointeurs, un pointeur est une variable qui stocke une adresse mémoire

int x=10; 
int *p; //this is a pointer to int 
p=&x; //now p has the memory location of x 
printf("%d\n",*p); //this will print 10