Valgrind sur Mac M1 et Windows : que faire en 2026
Valgrind ne tourne pas officiellement sur un Mac Apple Silicon ni sous Windows. Docker, WSL2, leaks, AddressSanitizer : ce que chacun détecte et ce qui lui échappe.
Un cours, un sujet ou un correcteur te demande de passer ton programme sous Valgrind. Sur ton Mac, le terminal répond zsh: command not found: valgrind, et brew install valgrind ne t'avance pas plus. Sous Windows, il n'existe tout simplement pas. Voici ce qui fonctionne en 2026, testé sur un Mac Apple Silicon, avec ce que chaque solution attrape et ce qu'elle laisse passer.
En bref
Valgrind est un outil Linux : sa version officielle ne prend en charge macOS que sur processeur Intel et pour des versions anciennes, et Windows n'a jamais fait partie de la liste. Sur un Mac Apple Silicon, la solution la plus fiable est de lancer Valgrind dans un conteneur Docker Linux, qui tourne en natif sur la puce ARM. Sous Windows, installe WSL2 puis sudo apt install valgrind. Sans Linux, leaks (macOS) trouve les fuites et AddressSanitizer les débordements, mais aucun des deux ne fait tout le travail de Memcheck.
Pourquoi Valgrind ne s'installe pas sur un Mac M1, M2 ou M3
Parce que Valgrind ne sait pas faire tourner le code d'un Mac à puce Apple. valgrind(1) exécute ton programme sur un processeur simulé et intercepte les appels au système : chaque couple processeur et système demande un portage à part. La liste officielle de valgrind.org contient Linux sur une dizaine d'architectures, FreeBSD, Solaris, Android, et pour macOS seulement X86/Darwin et AMD64/Darwin, c'est-à-dire les Mac Intel, avec la mention « macOS supported up to version 13 Ventura ». Les Mac ARM n'y figurent pas, y compris pour la version 3.27.1 publiée en mai 2026.
Homebrew en tire la conséquence : sa formule valgrind déclare depends_on :linux, elle ne s'installe pas sur macOS.
Il existe un portage non officiel, maintenu par Louis Brunner sur GitHub (valgrind-macos). Son tableau de compatibilité indique ARM64 pris en charge de macOS 11 à 14 puis sur macOS 26, et expérimental sur macOS 15. Il s'installe avec brew tap LouisBrunner/valgrind puis brew install --HEAD LouisBrunner/valgrind/valgrind, qui compile le projet depuis ses sources. Il n'a pas été testé pour cet article (la machine tourne sous macOS 27, absent de ce tableau à la date de publication). Retiens qu'il s'agit d'un projet tiers : une mise à jour de macOS peut le casser jusqu'au correctif suivant.
Sur Mac, la solution fiable : Valgrind dans Docker
Un conteneur Docker sur un Mac Apple Silicon fait tourner un vrai Linux ARM64, une plateforme que Valgrind prend officiellement en charge. Avec Docker Desktop installé, il suffit d'une image qui contient gcc et valgrind. Ce Dockerfile part de l'image officielle gcc:15 (une Debian 13) :
FROM gcc:15RUN apt-get update && apt-get install -y --no-install-recommends valgrind gdb make man-db manpages-dev && rm -rf /var/lib/apt/lists/*Construis l'image une fois, dans le dossier du Dockerfile :
docker build -t c-valgrind .Ensuite, depuis le dossier de ton projet, une seule commande compile et lance Valgrind sur tes fichiers. Le programme de test oublie de libérer un bloc :
#include <stdlib.h>#include <string.h>
int main(void){ char *copie = malloc(16);
strcpy(copie, "fuite"); return 0;}$ docker run --rm -v "$PWD":/src -w /src c-valgrind sh -c 'gcc -g fuite.c -o fuite && valgrind --leak-check=full ./fuite'==12== Memcheck, a memory error detector==12== Copyright (C) 2002-2024, and GNU GPL'd, by Julian Seward et al.==12== Using Valgrind-3.24.0 and LibVEX; rerun with -h for copyright info==12== Command: ./fuite==12== ==12== ==12== HEAP SUMMARY:==12== in use at exit: 16 bytes in 1 blocks==12== total heap usage: 1 allocs, 0 frees, 16 bytes allocated==12== ==12== 16 bytes in 1 blocks are definitely lost in loss record 1 of 1==12== at 0x488545C: malloc (vg_replace_malloc.c:446)==12== by 0x400653: main (fuite.c:6)==12== ==12== LEAK SUMMARY:==12== definitely lost: 16 bytes in 1 blocks==12== indirectly lost: 0 bytes in 0 blocks==12== possibly lost: 0 bytes in 0 blocks==12== still reachable: 0 bytes in 0 blocks==12== suppressed: 0 bytes in 0 blocks==12== ==12== For lists of detected and suppressed errors, rerun with: -s==12== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 0 from 0)-v "$PWD":/src monte ton dossier dans le conteneur, -w /src s'y place, --rm supprime le conteneur à la fin. Le rapport est celui de n'importe quel Linux : 16 octets perdus, alloués à fuite.c:6. Le détail de chaque ligne est expliqué dans Lire un rapport Valgrind.
Une conséquence à garder en tête : l'exécutable fuite compilé dans le conteneur est un programme Linux. Il apparaît dans ton dossier, mais ton Mac ne peut pas le lancer directement. Compile et exécute toujours du même côté.
Sous Windows : WSL2 et apt
Valgrind n'a jamais eu de version Windows officielle. Sa page des plateformes cite un portage externe développé entre 2011 et 2013, et précise que Windows n'est pas envisagé, le portage demandant tant de changements qu'il serait presque un projet séparé.
La voie normale passe par WSL2, le sous-système Linux de Windows. Sur Windows 10 version 2004 ou plus récent, ou sur Windows 11, une commande dans un PowerShell lancé en administrateur installe WSL2 et une Ubuntu :
wsl --installAprès le redémarrage, ouvre Ubuntu et installe le compilateur et Valgrind :
sudo apt updatesudo apt install build-essential valgrindTu obtiens la version de Valgrind de ta distribution (3.22 sur Ubuntu 24.04, 3.26 sur Ubuntu 26.04), et des rapports de la même forme que ceux de la section précédente, puisque Valgrind y tourne sur un vrai noyau Linux. Range tes projets dans ton dossier Linux (/home/ton-nom/...) plutôt que sous /mnt/c/ : Microsoft recommande de garder les fichiers du côté du système dont tu utilises les outils, pour la vitesse.
Si tu restes dans Visual Studio, son AddressSanitizer (option /fsanitize=address, depuis Visual Studio 2019 16.9) attrape les débordements et les accès après free. La détection de fuites n'en fait pas partie : Microsoft la range parmi les sanitizers qu'il pourrait ajouter plus tard.
Sans Linux sur Mac : leaks et AddressSanitizer
Deux outils sont disponibles directement sur macOS. Chacun couvre une partie de ce que fait Valgrind, et il faut les deux pour s'en approcher.
leaks, pour les fuites
leaks est fourni avec macOS. Avec -atExit, il lance le programme et cherche, au moment où il se termine, les blocs alloués que plus aucun pointeur ne désigne. Sortie obtenue sur macOS 27, Apple clang 21, puce Apple :
$ clang -g fuite.c -o fuite$ leaks -quiet -atExit -- ./fuiteProcess 90910 is not debuggable. Due to security restrictions, leaks can only show or save contents of readonly memory of restricted processes.
Process 90910: 185 nodes malloced for 10 KBProcess 90910: 1 leak for 32 total leaked bytes.
STACK OF 1 INSTANCE OF 'ROOT LEAK: <malloc in main>':2 dyld 0x18ad7fe80 start + 66881 fuite 0x100528480 main + 32 fuite.c:60 libsystem_malloc.dylib 0x18af7c630 _malloc_zone_malloc_instrumented_or_legacy + 152 ==== 1 (32 bytes) ROOT LEAK: <malloc in main 0x79de800000> [32]
$ echo $?1La fuite est trouvée, avec la ligne fuite.c:6 : -atExit active tout seul l'enregistrement des piles d'allocation (MallocStackLogging). Le message « not debuggable » veut seulement dire que leaks n'affichera pas le contenu des blocs. Le compte en octets diffère de celui de Valgrind, 32 pour un malloc(16) : fie-toi à la ligne plutôt qu'à la taille. Le code de retour vaut 1 quand il y a une fuite, 0 sinon, ce qui permet de l'utiliser dans un script. En revanche, leaks ne voit que les fuites : une écriture hors d'un bloc ou une variable non initialisée lui échappent.
AddressSanitizer, pour les débordements
AddressSanitizer est intégré à clang, donc au compilateur d'Apple. Il s'active à la compilation et arrête le programme au premier accès invalide. Ici, on copie six octets ("fuite" et son '\0') dans un bloc de cinq :
#include <stdlib.h>#include <string.h>
int main(void){ char *copie = malloc(5);
strcpy(copie, "fuite"); free(copie); return 0;}$ clang -g -fsanitize=address deborde.c -o deborde$ ./deborde===================================================================98812==ERROR: AddressSanitizer: heap-buffer-overflow on address 0x602000000955 at pc 0x000101532af4 bp 0x00016ef3e870 sp 0x00016ef3e020WRITE of size 6 at 0x602000000955 thread T0 #0 0x000101532af0 in strcpy+0x458 (libclang_rt.asan_osx_dynamic.dylib:arm64e+0x3aaf0) #1 0x000100ec0838 in main deborde.c:8 #2 0x00018ad7fe7c in start+0x1a1c (dyld:arm64e+0x31e7c)
0x602000000955 is located 0 bytes after 5-byte region [0x602000000950,0x602000000955)allocated by thread T0 here: #0 0x000101539274 in malloc+0x78 (libclang_rt.asan_osx_dynamic.dylib:arm64e+0x41274) #1 0x000100ec0824 in main deborde.c:6 #2 0x00018ad7fe7c in start+0x1a1c (dyld:arm64e+0x31e7c)
SUMMARY: AddressSanitizer: heap-buffer-overflow deborde.c:8 in main...Écriture de 6 octets, juste après un bloc de 5, à la ligne 8, dans un bloc alloué à la ligne 6. Sous Linux, AddressSanitizer cherche aussi les fuites à la fin du programme. La documentation de LLVM indique qu'on peut l'activer sur macOS avec ASAN_OPTIONS=detect_leaks=1. Avec le clang d'Apple sur puce Apple, la réponse est nette :
$ clang -g -fsanitize=address fuite.c -o fuite-asan$ ./fuite-asan$ ASAN_OPTIONS=detect_leaks=1 ./fuite-asan==90883==AddressSanitizer: detect_leaks is not supported on this platform.Sans l'option, le programme qui fuit se termine sans un mot. Sur un Mac Apple Silicon, compte donc sur AddressSanitizer pour les accès invalides et sur leaks pour les fuites.
Le terminal d'un exercice Grademe
Dernière option, sans rien installer : le terminal intégré aux exercices C de Grademe est un vrai Linux, avec gcc 15, gdb, Valgrind et les pages de manuel. Il faut un compte gratuit pour lancer du code. Le même fuite.c y donne :
$ gcc -g fuite.c -o fuite$ valgrind -q --leak-check=full ./fuite==14== 16 bytes in 1 blocks are definitely lost in loss record 1 of 1==14== at 0x490A754: malloc (vg_replace_malloc.c:446)==14== by 0x40007EF: main (fuite.c:6)==14==Cet environnement tourne sous Alpine avec la bibliothèque C musl et Valgrind 3.25 : les adresses changent, la ligne fautive reste la même. Certains exercices C y vérifient aussi la mémoire automatiquement avec Memcheck, en plus des tests de sortie.
read_the_leak
build_path renvoie le bon chemin à chaque appel, et les tests de texte passent tous. Mais elle perd un bloc à chaque fois, et c'est la vérification mémoire qui tranche. Lis le rapport, trouve l'allocation orpheline et répare la fonction avec seulement malloc et free.
Quelle solution choisir ?
| Solution | Système | Fuites | Débordements du tas | Valeurs non initialisées |
|---|---|---|---|---|
| Valgrind dans Docker | macOS, Windows, Linux | oui | oui | oui |
| Valgrind sous WSL2 | Windows | oui | oui | oui |
valgrind-macos (non officiel) | macOS | non testé ici | non testé ici | non testé ici |
leaks -atExit | macOS | oui | non | non |
| AddressSanitizer, clang d'Apple | macOS (puce Apple) | non | oui | non |
| AddressSanitizer, Visual Studio | Windows | non | oui | non |
| Terminal d'un exercice Grademe | navigateur | oui | oui | oui |
Les valeurs non initialisées sont le point fort de Memcheck : AddressSanitizer ne les cherche pas, c'est le rôle d'un autre outil de LLVM, MemorySanitizer, qui n'existe que sous Linux, NetBSD et FreeBSD. Si tu dois rendre un programme « propre sous Valgrind », vérifie-le sous Valgrind, dans Docker, WSL ou le terminal d'un exercice. Les outils de macOS servent à aller vite entre deux vérifications.
Questions fréquentes
Valgrind marche-t-il sur un Mac Intel ?
Officiellement, sur des versions anciennes de macOS seulement : la page d'accueil de valgrind.org annonce une prise en charge jusqu'à macOS 13 Ventura. Le portage non officiel valgrind-macos indique les Mac Intel compatibles jusqu'à macOS 26. Docker reste la solution qui ne dépend pas de ta version de macOS.
Pourquoi brew install valgrind ne marche pas sur Mac ?
Parce que la formule Homebrew de Valgrind exige Linux (depends_on :linux). Elle sert aux utilisateurs de Homebrew sous Linux. Sur Mac, il faut le dépôt tiers LouisBrunner/valgrind ou un Linux dans Docker.
Faut-il WSL 1 ou WSL 2 pour Valgrind ?
Prends WSL 2 : il fait tourner un vrai noyau Linux, là où WSL 1 traduisait les appels système, et c'est la version que wsl --install choisit par défaut. wsl -l -v affiche la version utilisée par chaque distribution.
Mon programme se comporte-t-il pareil dans Docker que sur mon Mac ?
Pas forcément. Le conteneur utilise un autre système, une autre bibliothèque C et souvent un autre compilateur. Un comportement indéfini peut passer inaperçu sur macOS et planter sous Linux, ou l'inverse. Teste-le donc dans l'environnement où il sera corrigé.
leaks ou AddressSanitizer, lequel lancer en premier ?
AddressSanitizer, parce qu'un accès invalide fausse tout ce qui suit, fuites comprises. Une fois qu'il ne signale plus rien, leaks -atExit vérifie que chaque malloc a son free.
Sources
