Cours sur la gestion de la mémoire
Posted: Sun Jan 18, 2026 7:06 pm
## La mémoire sous Windows
On continue avec un gros morceau : la mémoire.
Si tu comprends la mémoire sous Windows, tu comprends :
* pourquoi ça crash (0xC0000005)
* pourquoi ça leak
* pourquoi ça devient instable au bout de 2h
* pourquoi un bug “aléatoire” est en fait logique
Je vais te donner la vision claire + les fonctions Win32 indispensables (VirtualAlloc, HeapAlloc, mapping, protections, etc.).
---
### 1) Mémoire virtuelle vs mémoire physique
Sous Windows, ton programme voit une mémoire “virtuelle”.
Chaque processus a son propre espace d’adressage virtuel.
Deux processus peuvent utiliser la même adresse virtuelle sans partager la même RAM.
Le CPU (MMU) + Windows traduisent :
adresse virtuelle -> page physique (ou page du pagefile).
En user-mode, tu ne touches jamais la RAM physique directement.
---
### 2) Organisation générale d’un processus
Dans un processus tu as en gros :
* le code (.text)
* les données globales (.data / .bss)
* le heap (allocations dynamiques)
* les stacks (1 par thread)
* la mémoire mappée (DLL, fichiers, shared memory)
Important :
* chaque thread a son stack
* le heap est partagé entre threads du même processus
---
### 3) Stack vs Heap (différences utiles)
Stack :
* local au thread
* rapide
* taille limitée
* géré automatiquement (variables locales, appels de fonctions)
Heap :
* partagé dans le processus
* plus flexible
* plus lent
* c’est là que tu fais malloc/new (ou HeapAlloc)
Le heap est une source énorme de bugs :
* double free
* use-after-free
* buffer overflow
* race condition si plusieurs threads manipulent la même structure sans lock
---
### 4) Les heaps Windows (GetProcessHeap / HeapAlloc)
Windows a des heaps “Win32” gérés par le système.
Le plus courant : le heap du processus.
Fonctions indispensables :
* GetProcessHeap
* HeapAlloc
* HeapReAlloc
* HeapFree
Exemple minimal :
HeapReAlloc :
Très important :
* HeapFree libère le bloc, et après tu ne touches plus au pointeur.
* Si tu fais du multithread, protège les structures partagées (sinon tu auras des corruptions).
---
### 5) Créer son propre heap (HeapCreate / HeapDestroy)
Tu peux créer un heap dédié.
Utile si :
* tu veux isoler des allocations
* tu veux pouvoir tout libérer d’un coup
* tu veux limiter l’impact d’une corruption
Fonctions :
* HeapCreate
* HeapDestroy
Exemple :
Note :
* HeapDestroy détruit le heap (et donc libère tout ce qui reste dedans).
* Pratique pour éviter les leaks si tu structures bien ton code.
Fonctions utiles autour du heap :
* GetProcessHeaps (liste des heaps du process)
* HeapSize (taille d’un bloc)
* HeapValidate (détecter corruption, utile en debug)
* HeapCompact (tente de compacter)
* HeapWalk (parcourir, plutôt debug/outils)
* HeapSetInformation (config, certaines options de sécurité selon version)
---
### 6) Allocations bas niveau par pages (VirtualAlloc / VirtualFree)
Le heap travaille en “blocs”.
VirtualAlloc travaille en “pages mémoire”.
C’est la base du bas niveau Windows.
Fonctions indispensables :
* VirtualAlloc
* VirtualFree
* VirtualProtect
* VirtualQuery
Exemple :
VirtualProtect (changer les droits) :
VirtualQuery (inspecter une adresse : region, protections, état) :
---
### 7) Protections mémoire (et pourquoi ça crash)
Chaque page a des droits :
* lecture
* écriture
* exécution
Exemples :
* PAGE_READONLY
* PAGE_READWRITE
* PAGE_EXECUTE_READ
* PAGE_EXECUTE_READWRITE (à éviter en général)
* PAGE_NOACCESS
Le crash classique 0xC0000005 arrive quand :
* tu lis/écris à une adresse invalide
* tu écris dans une page non writable
* tu exécutes une page non executable
* tu utilises un pointeur NULL ou corrompu
C’est la base de 90% des crashs en C/C++.
---
### 8) Mémoire mappée (fichier ou shared memory)
Mapper un fichier en mémoire :
* très performant
* utile pour gros fichiers
* utile pour IPC (mémoire partagée)
Fonctions indispensables :
* CreateFileMapping
* OpenFileMapping
* MapViewOfFile
* UnmapViewOfFile
* FlushViewOfFile (si tu veux flush)
* CloseHandle
Exemple (schéma) :
---
### 9) Infos système utiles (taille de page, etc.)
Pour du bas niveau mémoire, tu dois connaître :
* taille de page
* allocation granularity
Fonctions indispensables :
* GetSystemInfo (ou GetNativeSystemInfo)
* GlobalMemoryStatusEx (infos RAM/commit, etc.)
Exemple :
---
### 10) Fonctions “legacy” (à connaître mais éviter)
Tu verras parfois :
* GlobalAlloc / GlobalFree
* LocalAlloc / LocalFree
C’est ancien et pas recommandé pour du code moderne.
Tu les rencontres dans du vieux code Win32, mais en 2026 tu fais plutôt :
* HeapAlloc
* VirtualAlloc
* new/malloc selon ton architecture
---
### 11) Règles simples (qui évitent 80% des bugs)
* Chaque allocation doit avoir sa libération (même chemin d’erreur).
* Ne mélange pas les familles :
* new/delete ensemble
* malloc/free ensemble
* HeapAlloc/HeapFree ensemble
* VirtualAlloc/VirtualFree ensemble
* Après un free, le pointeur est mort (mets le à NULL si besoin).
* Évite les gros tableaux sur le stack.
* En multithread, protège les structures partagées.
* Vérifie toujours les retours (NULL, GetLastError si nécessaire).
---
### 12) Liste “à connaître absolument” (résumé fonctions)
Heap (blocs) :
* GetProcessHeap
* HeapAlloc / HeapReAlloc / HeapFree
* HeapCreate / HeapDestroy
* HeapValidate / HeapSize
* GetProcessHeaps
Mémoire pages (bas niveau) :
* VirtualAlloc / VirtualFree
* VirtualProtect
* VirtualQuery
Mapping :
* CreateFileMapping / OpenFileMapping
* MapViewOfFile / UnmapViewOfFile
* FlushViewOfFile
Infos :
* GetSystemInfo / GetNativeSystemInfo
* GlobalMemoryStatusEx
---
Conclusion
La mémoire sous Windows, c’est :
* un espace virtuel par processus
* un stack par thread
* un heap partagé
* des pages avec des protections strictes
Et si tu maîtrises :
* HeapAlloc/Free
* VirtualAlloc/Protect/Query
* le mapping
tu as déjà un niveau solide en dev système.
A bientôt pour un prochain cours :
On continue avec un gros morceau : la mémoire.
Si tu comprends la mémoire sous Windows, tu comprends :
* pourquoi ça crash (0xC0000005)
* pourquoi ça leak
* pourquoi ça devient instable au bout de 2h
* pourquoi un bug “aléatoire” est en fait logique
Je vais te donner la vision claire + les fonctions Win32 indispensables (VirtualAlloc, HeapAlloc, mapping, protections, etc.).
---
### 1) Mémoire virtuelle vs mémoire physique
Sous Windows, ton programme voit une mémoire “virtuelle”.
Chaque processus a son propre espace d’adressage virtuel.
Deux processus peuvent utiliser la même adresse virtuelle sans partager la même RAM.
Le CPU (MMU) + Windows traduisent :
adresse virtuelle -> page physique (ou page du pagefile).
En user-mode, tu ne touches jamais la RAM physique directement.
---
### 2) Organisation générale d’un processus
Dans un processus tu as en gros :
* le code (.text)
* les données globales (.data / .bss)
* le heap (allocations dynamiques)
* les stacks (1 par thread)
* la mémoire mappée (DLL, fichiers, shared memory)
Important :
* chaque thread a son stack
* le heap est partagé entre threads du même processus
---
### 3) Stack vs Heap (différences utiles)
Stack :
* local au thread
* rapide
* taille limitée
* géré automatiquement (variables locales, appels de fonctions)
Heap :
* partagé dans le processus
* plus flexible
* plus lent
* c’est là que tu fais malloc/new (ou HeapAlloc)
Le heap est une source énorme de bugs :
* double free
* use-after-free
* buffer overflow
* race condition si plusieurs threads manipulent la même structure sans lock
---
### 4) Les heaps Windows (GetProcessHeap / HeapAlloc)
Windows a des heaps “Win32” gérés par le système.
Le plus courant : le heap du processus.
Fonctions indispensables :
* GetProcessHeap
* HeapAlloc
* HeapReAlloc
* HeapFree
Exemple minimal :
Code: Select all
#include <Windows.h>
#include <iostream>
int main()
{
HANDLE hHeap = GetProcessHeap();
```
int* p = (int*)HeapAlloc(hHeap, 0, sizeof(int));
if (!p) return 1;
*p = 123;
std::cout << *p << std::endl;
HeapFree(hHeap, 0, p);
return 0;
```
}
Code: Select all
p = (int*)HeapReAlloc(hHeap, 0, p, 10 * sizeof(int));
* HeapFree libère le bloc, et après tu ne touches plus au pointeur.
* Si tu fais du multithread, protège les structures partagées (sinon tu auras des corruptions).
---
### 5) Créer son propre heap (HeapCreate / HeapDestroy)
Tu peux créer un heap dédié.
Utile si :
* tu veux isoler des allocations
* tu veux pouvoir tout libérer d’un coup
* tu veux limiter l’impact d’une corruption
Fonctions :
* HeapCreate
* HeapDestroy
Exemple :
Code: Select all
HANDLE hHeap = HeapCreate(0, 0, 0);
if (!hHeap) return 1;
void* p = HeapAlloc(hHeap, 0, 256);
// ...
HeapFree(hHeap, 0, p);
HeapDestroy(hHeap);
* HeapDestroy détruit le heap (et donc libère tout ce qui reste dedans).
* Pratique pour éviter les leaks si tu structures bien ton code.
Fonctions utiles autour du heap :
* GetProcessHeaps (liste des heaps du process)
* HeapSize (taille d’un bloc)
* HeapValidate (détecter corruption, utile en debug)
* HeapCompact (tente de compacter)
* HeapWalk (parcourir, plutôt debug/outils)
* HeapSetInformation (config, certaines options de sécurité selon version)
---
### 6) Allocations bas niveau par pages (VirtualAlloc / VirtualFree)
Le heap travaille en “blocs”.
VirtualAlloc travaille en “pages mémoire”.
C’est la base du bas niveau Windows.
Fonctions indispensables :
* VirtualAlloc
* VirtualFree
* VirtualProtect
* VirtualQuery
Exemple :
Code: Select all
LPVOID mem = VirtualAlloc(
NULL,
4096,
MEM_RESERVE | MEM_COMMIT,
PAGE_READWRITE
);
if (!mem) return 1;
// utilisation...
VirtualFree(mem, 0, MEM_RELEASE);
Code: Select all
DWORD oldProt;
VirtualProtect(mem, 4096, PAGE_READONLY, &oldProt);
Code: Select all
MEMORY_BASIC_INFORMATION mbi;
VirtualQuery(mem, &mbi, sizeof(mbi));
### 7) Protections mémoire (et pourquoi ça crash)
Chaque page a des droits :
* lecture
* écriture
* exécution
Exemples :
* PAGE_READONLY
* PAGE_READWRITE
* PAGE_EXECUTE_READ
* PAGE_EXECUTE_READWRITE (à éviter en général)
* PAGE_NOACCESS
Le crash classique 0xC0000005 arrive quand :
* tu lis/écris à une adresse invalide
* tu écris dans une page non writable
* tu exécutes une page non executable
* tu utilises un pointeur NULL ou corrompu
C’est la base de 90% des crashs en C/C++.
---
### 8) Mémoire mappée (fichier ou shared memory)
Mapper un fichier en mémoire :
* très performant
* utile pour gros fichiers
* utile pour IPC (mémoire partagée)
Fonctions indispensables :
* CreateFileMapping
* OpenFileMapping
* MapViewOfFile
* UnmapViewOfFile
* FlushViewOfFile (si tu veux flush)
* CloseHandle
Exemple (schéma) :
Code: Select all
HANDLE hMap = CreateFileMapping(
hFile,
NULL,
PAGE_READWRITE,
0, 0,
NULL
);
LPVOID view = MapViewOfFile(
hMap,
FILE_MAP_ALL_ACCESS,
0, 0, 0
);
// utilisation via pointeur...
UnmapViewOfFile(view);
CloseHandle(hMap);
### 9) Infos système utiles (taille de page, etc.)
Pour du bas niveau mémoire, tu dois connaître :
* taille de page
* allocation granularity
Fonctions indispensables :
* GetSystemInfo (ou GetNativeSystemInfo)
* GlobalMemoryStatusEx (infos RAM/commit, etc.)
Exemple :
Code: Select all
SYSTEM_INFO si;
GetSystemInfo(&si);
// si.dwPageSize, si.dwAllocationGranularity, etc.
### 10) Fonctions “legacy” (à connaître mais éviter)
Tu verras parfois :
* GlobalAlloc / GlobalFree
* LocalAlloc / LocalFree
C’est ancien et pas recommandé pour du code moderne.
Tu les rencontres dans du vieux code Win32, mais en 2026 tu fais plutôt :
* HeapAlloc
* VirtualAlloc
* new/malloc selon ton architecture
---
### 11) Règles simples (qui évitent 80% des bugs)
* Chaque allocation doit avoir sa libération (même chemin d’erreur).
* Ne mélange pas les familles :
* new/delete ensemble
* malloc/free ensemble
* HeapAlloc/HeapFree ensemble
* VirtualAlloc/VirtualFree ensemble
* Après un free, le pointeur est mort (mets le à NULL si besoin).
* Évite les gros tableaux sur le stack.
* En multithread, protège les structures partagées.
* Vérifie toujours les retours (NULL, GetLastError si nécessaire).
---
### 12) Liste “à connaître absolument” (résumé fonctions)
Heap (blocs) :
* GetProcessHeap
* HeapAlloc / HeapReAlloc / HeapFree
* HeapCreate / HeapDestroy
* HeapValidate / HeapSize
* GetProcessHeaps
Mémoire pages (bas niveau) :
* VirtualAlloc / VirtualFree
* VirtualProtect
* VirtualQuery
Mapping :
* CreateFileMapping / OpenFileMapping
* MapViewOfFile / UnmapViewOfFile
* FlushViewOfFile
Infos :
* GetSystemInfo / GetNativeSystemInfo
* GlobalMemoryStatusEx
---
Conclusion
La mémoire sous Windows, c’est :
* un espace virtuel par processus
* un stack par thread
* un heap partagé
* des pages avec des protections strictes
Et si tu maîtrises :
* HeapAlloc/Free
* VirtualAlloc/Protect/Query
* le mapping
tu as déjà un niveau solide en dev système.
A bientôt pour un prochain cours :