Bonjour a tous,
Je me demandais si il etait possible de recuperer la zone memoire dans laquelle sont stockes les globales, histoire de faire une recherche dedans.
Je bosse en C/C++ sous Visual studio.
Merci d'avance.
Bonjour a tous,
Je me demandais si il etait possible de recuperer la zone memoire dans laquelle sont stockes les globales, histoire de faire une recherche dedans.
Je bosse en C/C++ sous Visual studio.
Merci d'avance.
c'est pas très propre...
un executable contient des sections, deux d'entre elle (appelées DATA et RDATA je crois) sont utilisées comme espace pour les variables globales.
Lorsque l'executable est chargé en mémoire, le systeme d'exploitation va charger ces deux sections en même temps que le code, du coup c'est la que seront les variables globales.
Pour savoir ou elles seront stockées en mémoire, il faut "ouvrir" l'executable avec un programme approprié et inspecter l'en-tête. Clui-ci contient les informations de chargement et a partir de ces informations ont peut calculer ou cela sera stocké lorsque le programme est chargé.
Si tu veux que le programme le fasse depuis lui-même, il faudrait qu'il soit capable de trouver son propre fichier executable (facile avec argv[0]), l'ouvrir, regarder les sections, trouver celle qui t'interesse, calculer l'emplacement ou elle est chargée et bingo.
Si tu veux modifier les variables globales d'un autre programme, c'est plus complexe.
Je sais que c'est moyennement propre, mais j'essaye de developper un outil capable de trouver les memory leaks. J'ai besoin de parcourir ma liste de globale pour savoir si il existe des references sur mes pointeurs en memoire dans celle-ci. Du coup, ca sera de la lecture seulement. Et sur le programme lui-meme.
J'ai reussi a trouver des API telles que VirtualQuery. Appele avec un pointeur sur la stack, elle me donne la zone memoire que j'aurai a parcourir. Le seul soucis, c'est que je n'ai que des zones memoires, et que donc je n'ai pas vraiment moyen de connaitre toutes les zones memoires qui stockent des globales (a moins d'appeler cette API pour toutes mes globales, ce qui n'est pas acceptable...)
sous gcc, le linker ajoutent automatiquement des symboles bien pratiques pour ca:
sous visual C++, c'est beaucoup plus compliqué (snif)
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13 #include <cstdio> extern "C" const char *_data_start__; extern "C" const char *_data_end__; static int x = 4; static const int y = 3; int main() { printf("data segment: 0x%p-0x%p\n", &_data_start__, &_data_end__); printf("x: 0x%p\n", &x); printf("y: 0x%p\n", &y); }
ce code la retourne les pages réservées. Pour une raison que je ne connais pas, le range retourné est plus grand que la taille totale chez moi, je ne sais pas ce qu'il y a au début.
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60 #include <windows.h> #include <cstdio> static char begin; static char block1[1274654]; static char dummy; static char block2[4817219]; static char end; static const void* _data_start; static const void* _data_end; static void findDataSegment() { SYSTEM_INFO system; size_t pageMask; const void* p; GetSystemInfo(&system); pageMask = ~(system.dwPageSize - 1); _data_start = _data_end = (const void*)((ptrdiff_t)(&dummy) & pageMask); do { MEMORY_BASIC_INFORMATION buf; const void* p = (const void*)(((ptrdiff_t)(char*)_data_start-1) & pageMask); size_t result = VirtualQuery(p, &buf, sizeof(buf)); if(result != sizeof(buf)) break; if(buf.AllocationBase == 0) break; _data_start = buf.BaseAddress; } while(1); do { MEMORY_BASIC_INFORMATION buf; const void* p = (const void*)(((ptrdiff_t)(char*)_data_end+1) & pageMask); size_t result = VirtualQuery(p, &buf, sizeof(buf)); if(result != sizeof(buf)) break; if(buf.AllocationBase == 0) break; _data_end = (char*)buf.BaseAddress + buf.RegionSize; } while(1); } int main() { memset(block1, 1, sizeof(block1)); memset(block2, 1, sizeof(block2)); findDataSegment(); printf("data segment: 0x%p-0x%p\n", _data_start, _data_end); printf("begin: 0x%p\n", &begin); printf("block1: 0x%p-%p\n", &block1[0], &block1[sizeof(block1)]); printf("block2: 0x%p-%p\n", &block2[0], &block2[sizeof(block2)]); printf("dummy: 0x%p\n", &dummy); printf("end: 0x%p\n", &end); }
C'est complètement non portable et si ca crashe horriblement, ca ne m'etonnera meme pas.
Une autre solution plus fiable serait d'utiliser un garbage collector, comme boehm GC, qui peut s'utiliser en mode "detection de leaks"
Partager