bonjour
je sais comment trouver "l'adresse memoire" de "debut" de la "zone memoire" d'un processus.
comment je pourrai trouvez l'adresse memoire de sa fin ?
merci pour votre aide
bonjour
je sais comment trouver "l'adresse memoire" de "debut" de la "zone memoire" d'un processus.
comment je pourrai trouvez l'adresse memoire de sa fin ?
merci pour votre aide
comment ?Envoyé par ilimo
C'est spécifique a chaque OS. Y'a pas vraiment de fin dans la mesure ou il y a des "trous", et que des dlls systemes sont mappés dans l'espace mémoire de ton process, que y'a des parties en lecture seule, etc... Et que surtout ca évolue constament.
_____________________________________________________________
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 void Process_Adress_Debut() { hProcess_Open = OpenProcess(PROCESS_ALL_ACCESS, FALSE, proc_id_); hModuleSnap = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE, proc_id_); if (hModuleSnap == INVALID_HANDLE_VALUE) { printf("snapshot impossible"); } me32.dwSize = sizeof(MODULEENTRY32); Module32First( hModuleSnap, &me32 ); do { Module32Next( hModuleSnap, &me32 ); if(StrCmp(me32.szModule, "MyProcess.dll")== 0) { printf( "\n dll name : %s", me32.szModule ); printf( "\n base address = 0x%08X", (DWORD) me32.modBaseAddr ); MyProcess_BaseAdr = (DWORD) me32.modBaseAddr; } } while( StrCmp(me32.szModule, "MyProcess.dll")!= 0); CloseHandle(hModuleSnap); }
Chaque donnée stockée en mémoire principale (variable, fonction) a un emplacement unique, ceci lors de la meme execution( lors d'une autre, ça change)que surtout ca évolue constament
L'allocation dynamique de mémoire permet la réservation d'un espace mémoire
Effectuer une allocation dynamique de mémoire, c'est demander au système de vous réserver un bloc de mémoire, que vous pourrez utiliser à votre convenance
_____________________________________________________________
ainsi, à chaque nouvelle execution de Myprocess.dll, je calcule l'adresse de base.
de cette manière toutes les données manipulées par Myprocess.dll
sont stockées dans des adresses mémomoires à partir de l'adresse memoire de base.
on peut ignorer tout ce qui est avant cette adresse base.
mais ce processus jusqu'à quelle adresse prend de l'espace ??
Si tu effectues plusieurs alloc, tu as donc plusieurs blocs mémoire réservés par le systeme... et des "trous" = fragmentation. Et un bloc alloué se libere... donc ca évolue a chaque allocation / libération, c.a.d constament. Fait une petite recherche sur le working set size sous Windows, et tu vas mieux comprendre. Exemple simple:
Lance une appli, regarde sa consommation mémoire dans le gestionnaire des taches (Le "Mem Usage", = working set size). Minimise l'application et observe comment ca évolue... Et l'appli n'y est pour rien, c'est Windows qui gere l'espace mémoire du process, en fonction des dlls mappées etc...
Sinon, ton code et ta question sont spécifiques Windows. Tout ton code de Process_Adress_Debut() ne sert a rien vu que Windows te donnes cette "adresse de début" en 1er parametre de DllMain.
Et un simple GetModuleHandle("MyProcess.dll") ferait la meme chose.
Tu mélanges dll et process. L'adresse recue / renvoyée par ta fonction n'est pas l'adresse "de début" du process, mais l'adresse a laquelle est mappée ta dll.ainsi, à chaque nouvelle execution de Myprocess.dll, je calcule l'adresse de base.
de cette manière toutes les données manipulées par Myprocess.dll
sont stockées dans des adresses mémomoires à partir de l'adresse memoire de base.
on peut ignorer tout ce qui est avant cette adresse base.
Il y a de tres fortes chances que ta dll alloue de la mémoire avant cette adresse. Fais juste un test, pour voir, sur l'adresse renvoyée par new. Car l'adresse du tas est tres certainement située avant celle de ta dll. Pire, ta dll peut utiliser la meme CRT que l'exe, ce qui a pour consequence que ta dll utilise la meme memoire que l'exe.
Il ne prend pas un gros bloc contiguë, mais plein de blocs plus ou moins gros, avec des "trous" entre-eux.mais ce processus jusqu'à quelle adresse prend de l'espace ??
La grande question est : qu'essayes-tu de faire ? Pourquoi as-tu besoin de cette info ?
Euh, au sujet des GetModuleHandle()...
Je ne voudrais pas paraître défaitiste, mais d'après la structure MODULEENTRY32, handle de module et adresse de base sont deux choses différentes...
SVP, pas de questions techniques par MP. Surtout si je ne vous ai jamais parlé avant.
"Aw, come on, who would be so stupid as to insert a cast to make an error go away without actually fixing the error?"
Apparently everyone. -- Raymond Chen.
Traduction obligatoire: "Oh, voyons, qui serait assez stupide pour mettre un cast pour faire disparaitre un message d'erreur sans vraiment corriger l'erreur?" - Apparemment, tout le monde. -- Raymond Chen.
Et poutant... Le HMODULE est un reliquat de Win16, ca n'a plus de sens de nos jours. Code modifié:
résultat:
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 #include <windows.h> #include <Tlhelp32.h> #include <stdio.h> void Process_Adress_Debut() { DWORD proc_id_ = GetCurrentProcessId(); HANDLE hProcess_Open = OpenProcess(PROCESS_ALL_ACCESS, FALSE, proc_id_); HANDLE hModuleSnap = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE, proc_id_); if (hModuleSnap == INVALID_HANDLE_VALUE) { printf("snapshot impossible"); } MODULEENTRY32 me32 = {0}; me32.dwSize = sizeof(MODULEENTRY32); Module32First( hModuleSnap, &me32 ); do { Module32Next( hModuleSnap, &me32 ); if(strcmp(me32.szModule, "kernel32.dll")== 0) { printf( "\n dll name : %s", me32.szModule ); printf( "\n base address = 0x%08X", (DWORD) me32.modBaseAddr ); printf( "\n hModule = 0x%08X", (DWORD) me32.hModule ); } } while( strcmp(me32.szModule, "kernel32.dll")!= 0); CloseHandle(hModuleSnap); } int main() { Process_Adress_Debut(); printf( "\n GetModuleHandle(kernel32) = 0x%08X", GetModuleHandle( "kernel32.dll" ) ); }
dll name : kernel32.dll
base address = 0x7C800000
hModule = 0x7C800000
GetModuleHandle(kernel32) = 0x7C800000
OK.
Pour moi, c'est plutôt le HINSTANCE qui est un reliquat, et je pensais le HMODULE légitime (et donc, potentiellement différent de son adresse de base).
D'ailleurs, je ne sais pas si même de nos jours, c'est garanti officiellement par l'API. Surtout sachant qu'il y a quand même deux champs dans une structure 32 bits...
SVP, pas de questions techniques par MP. Surtout si je ne vous ai jamais parlé avant.
"Aw, come on, who would be so stupid as to insert a cast to make an error go away without actually fixing the error?"
Apparently everyone. -- Raymond Chen.
Traduction obligatoire: "Oh, voyons, qui serait assez stupide pour mettre un cast pour faire disparaitre un message d'erreur sans vraiment corriger l'erreur?" - Apparemment, tout le monde. -- Raymond Chen.
Ca doit etre pour que du vieux code compile. De meme que wParam n'est plus un WORD depuis longtemps...
Dans le cas de kernel32, l'OS te garantit que son adresse de base est toujours 0x7C800000.
Pour compiler du vieux code, il n'y aurait pas 32 dans le nom...
Surtout que les processus n'existaient pas en 16-bits, ni ToolHelp32, à mon avis.
Peut-être que ça pouvait être différent sous les Windows non-NT ?
SVP, pas de questions techniques par MP. Surtout si je ne vous ai jamais parlé avant.
"Aw, come on, who would be so stupid as to insert a cast to make an error go away without actually fixing the error?"
Apparently everyone. -- Raymond Chen.
Traduction obligatoire: "Oh, voyons, qui serait assez stupide pour mettre un cast pour faire disparaitre un message d'erreur sans vraiment corriger l'erreur?" - Apparemment, tout le monde. -- Raymond Chen.
Win 3.x était multiprocess coopératif. Le 16 bits n'empêche pas le multiprocess, tant qu'on est en mode protégé. La première version d'OS/2 était en 16 bits.
Windows NT a été 32 bits depuis le début (a la base, il devait être un successeur à OS/2).
Concernant le cas particulier de MODULEENTRY32, je dois avouer que j'en sais rien. C'est juste que bien souvent, dans ce genre de cas, la réponse se trouve du coté de la compatibilité ascendante.
il y a des trous même dans la zone mémoire réservée à une variable?
Parceque sinon on pourrait faire:
fin pointerait sur le bit juste après le dernier bit de la variable.
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2 bool *debut = (bool*)(void*)(&variable); bool *fin = debut + sizeof(variable);
on pourrait faire --fin pour le faire pointer sur le dernier bit.
Non, bien sur que non. Il faut avoir une vision plus générale que le C++, au niveau de l'OS. En mémoire ton programme possède une zone de code, de mémoire, de mémoire readonly, etc... C'est le cas pour ton exe, et pour les dlls. Et ton process, c'est 1 exe + x dlls, donc autant de zones en mémoire, avec des trous entre-elles.Envoyé par coyotte507
Une image pour un peu mieux comprendre:
http://www.flounder.com/hooks.htm
Du point de vue du C++, tu compiles 1 exe ou 1 dll, donc avec sa propre zone de mémoire a elle = le tas, qui est bien un bloc entier contigüe, sans trou (encore que, le compilo peut en fait gérer plusieurs tas, et alors...).
Attendez... je vais peut-etre sortir une énormité....
Mais il me semblait que de toute maniere, on avait qu'un 'mapping' de la mémoire...
Je veux dire, tout process se trouve attribué 2Go (sous 32-bits) d'espace d'addressage... et l'OS se charge de mapper ca sur des vraies addresses dynamiquement.
Mise à part, bien sur, le petit Go sensé être "partagé" (et qui ne l'est plus depuis longtemps) pour les I/O et autres joyeusetés...
Un GetProcAddress, HMODULE, ou autre, ne renvoit qu'une addresse dans cet espace virtuel, et ne représente en rien la quantité de mémoire allouée, ou la (les) zones occupées....
A part taper dans les tables de page mémoire (OS kernel) et demander lequelles sont allouées, et ou ...
Ou alors, j'ai vraiment rien compris de la problématique initiale![]()
En 32 bits il y a virtuellement 4 Go d'espace d'adressage virtuel. Mais l'OS se réserve 1 Go, et il reste donc 3 Go pour le process : 2Go pour lui + 1Go pour les données partagées. Si ton exe est marqué d'un flag spécial, et que Windows a été démarré avec le switch /3GB, ton process aura droit a 3Go pour son usage personnel.Envoyé par nicroman
Cet espace d'adressage est découpé en petit morceaux = des pages, qui peuvent etre individuellement marqués commes accessibles ou non au process. Sous x86, une page fait 4ko. Une meme page peut etre mappée dans différents espaces virtuels de plusieurs process, a des adresses virtuelles différentes.
En réalité, sous Windows, la taille du plus petit bloc de mémoire virtuelle adressable n'est pas 4Ko mais 64Ko.VirtualAlloc(), la fonction systeme d'allocation mémoire de base, sur laquelle toutes les autres sont basées, arrondit a 64Ko.
http://blogs.msdn.com/oldnewthing/ar.../08/55239.aspx
Toutes les autres fonctions vont utiliser VirtualAlloc pour subdiviser des blocs de 64Ko en plus petits blocs. Donc, du point de vue de l'OS, seule la mémoire allouée via VirtualAlloc compte, et elle consiste en blocs de 64Ko.
Windows va donc ajuster ton espace d'adressage virtuel a coup de plages de 64Ko. Ces plages ne sont pas forcément entierement mappées en mémoire physique. Elle le sont a coup de pages physiques, donc 4Ko sous x86. Par exemple, quand tu lances un exe, Windows va réserver de l'espace virtuel pour l'ensemble du code exécutable, mais ne va effectivement charger en mémoire que les pages réellement demandée en exécution.
Si tu alloues 1 octet avec VirtualAlloc, Windows va élargir ton espace d'adressage de 64Ko, et commiter 4Ko en mémoire physique. Le reste de la mémoire virtuelle (64Ko - 4Ko) est perdu. Pour éviter cela, la CRT de ton compilateur C++ va, par exemple, allouer 64Ko, et les remplir petit a petit au fur et a mesure de tes allocations avec new/malloc. Au passage il rajoute des trucs pour vérifier que la mémoire n'est pas corrompue, etc...
Je ne crois pas que ca ait été dit quelque part. Il est tres difficile de calculer la mémoire utilisée par un process, car il y a différents types de mémoire, a comencer par la mémoire partagée. Si tu lances 2 fois le meme exe, son code exécutable va etre partagé en RAM. Comment comptabiliser cette mémoire partagée ?Un GetProcAddress, HMODULE, ou autre, ne renvoit qu'une addresse dans cet espace virtuel, et ne représente en rien la quantité de mémoire allouée, ou la (les) zones occupées....
En ce qui me concerne, par quantité de mémoire allouée, je parle de la mémoire dynamiquement allouée pour les données, et qui est spécifique a chaque process. Si le process se termine, cette mémoire est effectivement récupérée. C'est la colonne "Taille MV" du gestionnaire de tache, non visible par défaut.
Il y a les fonctions de la PSAPI:A part taper dans les tables de page mémoire (OS kernel) et demander lequelles sont allouées, et ou ...
http://msdn2.microsoft.com/en-us/library/ms684894.aspx
Partager