Les membres ayant 30 points peuvent parler sur les canaux annonces, projets et hs du chat.
La shoutbox n'est pas chargée par défaut pour des raisons de performances. Cliquez pour charger.

Forum Casio - Projets de programmation


Index du Forum » Projets de programmation » MemTrack - Détection de fuites mémoire
Farhi Hors ligne Membre Points: 1427 Défis: 0 Message

MemTrack - Détection de fuites mémoire

Posté le 02/04/2025 19:40

Hello les gens !
Voici un petit système pour détecter les fuites mémoire dynamiques dans un programme Casio utilisant gint, compatible aussi bien en C qu’en C++.

Le but est simple : à la fin du programme, savoir combien de blocs mémoire n'ont pas été libérés, même ceux alloués dans des libs externes.

Fonctionnalités
- Remplace malloc/free et new/delete par une version trackée
- Compatible avec les appels depuis des libs .a
- Affiche automatiquement un message à la fin du programme
- Optionnel, activable/désactivable via CMake
- Aucun outil externe requis
- Ne modifie pas gint ou la libc

Intégration
1. Copier le fichier memtrack.h/.hpp dans votre projet :
#if !defined(MEMTRACK_H) && defined(MEMTRACK_ENABLED)
#define MEMTRACK_H
#include <stdlib.h>
#include <stdio.h>
#include <gint/gint.h>
#include <gint/keyboard.h>
#include <gint/display.h>
#include <gint/kmalloc.h>

#ifdef __cplusplus
extern "C" {
#endif

// --- Compteur global ---
static int memtrack_alloc_count = 0;

void memtrack_init(void)
{
    memtrack_alloc_count = 0;
}

// --- malloc/free overrides ---
void* malloc(size_t size)
{
    ++memtrack_alloc_count;
    return kmalloc(size, NULL);
}

void free(void* ptr)
{
    --memtrack_alloc_count;
    kfree(ptr);
}

void* calloc(size_t count, size_t size) {
    ++memtrack_alloc_count;
    return kmalloc(count * size, NULL);
}

void* realloc(void* ptr, size_t size) {
    return krealloc(ptr, size);
}

// --- Report à la fin du programme ---
__attribute__((destructor))
static void memtrack_report_leaks(void)
{
    dclear(C_BLACK);
    if(memtrack_alloc_count > 0) {
        char buffer[64];
        snprintf(buffer, sizeof(buffer), "Memory leak: %d block(s)", memtrack_alloc_count);
        dprint(1, 1, C_WHITE, buffer);
    } else {
        dprint(1, 1, C_WHITE, "No memory leaks!");
    }
    dupdate();
    getkey(); // pause
}

#ifdef __cplusplus
}
#endif

// --- Opérateurs C++ ---
#ifdef __cplusplus

#include <new>

void* operator new(std::size_t size)
{
    return malloc(size);
}

void* operator new[](std::size_t size)
{
    return malloc(size);
}

void operator delete(void* ptr) noexcept
{
    free(ptr);
}

void operator delete[](void* ptr) noexcept
{
    free(ptr);
}

void operator delete(void* ptr, unsigned int)
{
    free(ptr);
}
void operator delete[](void* ptr, unsigned int)
{
    free(ptr);
}

#endif // __cplusplus

#endif // MEMTRACK_ENABLED


2. Dans main() : reset du compteur
#include "memtrack.hpp"

int main(void)
{
    memtrack_init(); // Ignore les allocations faites avant main()
    
    //code...
    return 1;
}


3. Dans CMakeLists.txt
Ajouter en haut cette ligne (ON ou OFF) :
option(MEMTRACK "Enable memory leak tracking" ON)

Et ajouter les lignes suivantes :
if(MEMTRACK)
    target_compile_definitions(myaddin PRIVATE MEMTRACK_ENABLED=1)
    target_compile_options(myaddin PRIVATE
        -fno-builtin-malloc
        -fno-builtin-free
        -fno-builtin-realloc
        -fno-builtin-calloc
        -fno-builtin-new
        -fno-builtin-delete
    )
endif()

Voilà en espérant que cela peut vous être utile

PS : Je me suis cassé la tête à chercher dans tout gint la fonction builtin de malloc et free, j'ai trouvé que ça, s'il y a un problème, signalé le moi


Fcalva Hors ligne Membre Points: 620 Défis: 10 Message

Citer : Posté le 02/04/2025 23:57 | #


Les fonctions internes de gint sont dans kmalloc, après c'est intéressant de toucher à ça que si tu compte faire une pr
Le malloc()/free() standards sont dans la libc, plus précisément dans src/stdlib/
Apréciateur de Noctua moyen
Caltos : G35+EII, G90+E (briquée )
Lephenixnoir Hors ligne Administrateur Points: 24988 Défis: 174 Message

Citer : Posté le 03/04/2025 08:29 | #


Pas de problème avec ta méthode, je pense ! Je sais pas comment j'ai raté ça dans ta question précédente. x)
Tu peux même enregistrer file/line avec les allocations en vrai, pour les diagnostics :o
Mon graphe (28 Janvier): (MPM ; serial gint ; (Rogue Life || HH2) ; PythonExtra ; ? ; Boson X ; passe gint 3 ; ...) || (shoutbox v5 ; v5)
Farhi Hors ligne Membre Points: 1427 Défis: 0 Message

Citer : Posté le 03/04/2025 17:42 | #


Fcalva a écrit :
Les fonctions internes de gint sont dans kmalloc, après c'est intéressant de toucher à ça que si tu compte faire une pr
Le malloc()/free() standards sont dans la libc, plus précisément dans src/stdlib/

Ouai j'ai vu ça, mais le souci d'utiliser la libc c'est que ça crée une récursion infinie, c'est pour ça que j'ai utilisé kmalloc.

Lephenixnoir a écrit :
Pas de problème avec ta méthode, je pense ! Je sais pas comment j'ai raté ça dans ta question précédente. x)
Tu peux même enregistrer file/line avec les allocations en vrai, pour les diagnostics :o

Je n'ai pas compris ce que tu veux dire avec file/line ?
"La créativité est contagieuse faites la tourner"
Albert Einstein
Lephenixnoir Hors ligne Administrateur Points: 24988 Défis: 174 Message

Citer : Posté le 03/04/2025 17:51 | #


Puisque tu définis tes propres fonctions, tu as l'option d'insérer les macros __FILE__ et __LINE__ en paramètre aux fonctions (au moins pour malloc/free, les opérateurs C++ c'est plus dur sans doute...) et du garder cette info de provenance dans un coin (e.g. les 8 premiers octets de l'allocation) pour qu'en cas de fuite tu puisses dire qui a alloué.
Mon graphe (28 Janvier): (MPM ; serial gint ; (Rogue Life || HH2) ; PythonExtra ; ? ; Boson X ; passe gint 3 ; ...) || (shoutbox v5 ; v5)
Farhi Hors ligne Membre Points: 1427 Défis: 0 Message

Citer : Posté le 03/04/2025 19:22 | #


Lephenixnoir a écrit :
Puisque tu définis tes propres fonctions, tu as l'option d'insérer les macros __FILE__ et __LINE__ en paramètre aux fonctions (au moins pour malloc/free, les opérateurs C++ c'est plus dur sans doute...) et du garder cette info de provenance dans un coin (e.g. les 8 premiers octets de l'allocation) pour qu'en cas de fuite tu puisses dire qui a alloué.

J'avais vu ça mais le problème c'est que les macro ne peuvent pas remplacer les fonctions malloc et free qui sont à l'intérieur d'une lib.

Par contre il y a un truc que je ne comprend pas, pourquoi quand je fais un gint_world_switch mon memtrack_alloc_count est reset alors que je fait un leak ((void)image_alloc(20,20,1);) volontairement avant le gint_world_switch ?

[Edit] En fait non c'est bon j'ai trouvé le problème, c'est parce que j'avais oublié de géré calloc
"La créativité est contagieuse faites la tourner"
Albert Einstein

LienAjouter une imageAjouter une vidéoAjouter un lien vers un profilAjouter du codeCiterAjouter un spoiler(texte affichable/masquable par un clic)Ajouter une barre de progressionItaliqueGrasSoulignéAfficher du texte barréCentréJustifiéPlus petitPlus grandPlus de smileys !
Cliquez pour épingler Cliquez pour détacher Cliquez pour fermer
Alignement de l'image: Redimensionnement de l'image (en pixel):
Afficher la liste des membres
:bow: :cool: :good: :love: ^^
:omg: :fusil: :aie: :argh: :mdr:
:boulet2: :thx: :champ: :whistle: :bounce:
valider
 :)  ;)  :D  :p
 :lol:  8)  :(  :@
 0_0  :oops:  :grr:  :E
 :O  :sry:  :mmm:  :waza:
 :'(  :here:  ^^  >:)

Σ π θ ± α β γ δ Δ σ λ
Veuillez donner la réponse en chiffre
Vous devez activer le Javascript dans votre navigateur pour pouvoir valider ce formulaire.

Si vous n'avez pas volontairement désactivé cette fonctionnalité de votre navigateur, il s'agit probablement d'un bug : contactez l'équipe de Planète Casio.

Planète Casio v4.3 © créé par Neuronix et Muelsaco 2004 - 2025 | Il y a 98 connectés | Nous contacter | Qui sommes-nous ? | Licences et remerciements

Planète Casio est un site communautaire non affilié à Casio. Toute reproduction de Planète Casio, même partielle, est interdite.
Les programmes et autres publications présentes sur Planète Casio restent la propriété de leurs auteurs et peuvent être soumis à des licences ou copyrights.
CASIO est une marque déposée par CASIO Computer Co., Ltd