Page suivante Page précédente Table des matières

17. Annexe D my_malloc.cpp

Vous pouvez récupérer tous les programmes en un seul tar.gz sur Telecharger String . Pour obtenir ce fichier, dans un butineur web, sauvez ce fichier en type 'texte'.


//*****************************************************************
// La licence de distribution est la GNU/GPL et vous devez inclure
// le nom et le mel de l'auteur dans toutes les copies
// Auteur : Al Dev    Mel : alavoor@yahoo.com
//*****************************************************************

#include <stdio.h>
#include <alloc.h>  // pour malloc, alloc etc...
#include <stdlib.h>  // malloc, alloc..
#include <time.h>  // strftime, localtime, ...
#include <list.h>  // strftime, localtime, ...  voir include/g++/stl_list.h
//#include <debug.h> // debug_("a", a);  debug2_("a", a, true);

#include "my_malloc.h"

const short SAFE_MEM = 10;
const short DATE_MAX_SIZE = 200;

const short MALLOC = 1;
const short REALLOC     = 2;

const short VOID_TYPE =         1;
const short CHAR_TYPE =         2;
const short SHORT_TYPE =        3;
const short INT_TYPE =          4;
const short LONG_TYPE =         5;
const short FLOAT_TYPE =        6;
const short DOUBLE_TYPE =       7;

const char LOG_FILE[30] = "memory_error.log";

// Décommenter cette ligne pour déboguer la totalité de la mémoire allouée
//#define DEBUG_MEM  "debug_memory_sizes_allocated"

static void raise_error_exit(short mtype, short datatype, char fname[], int lineno);

void local_my_free(void *aa, char fname[], int lineno)
{
        if (aa == NULL)
                return;
        //call_free_check(aa, fname, lineno);
        free(aa);
        aa = NULL;
}

// size_t est défini comme un entier long non signé (unsigned long)
void *local_my_malloc(size_t size, char fname[], int lineno) 
{
        size_t  tmpii = size + SAFE_MEM;
        void *aa = NULL;
        aa = (void *) malloc(tmpii);
        if (aa == NULL)
                raise_error_exit(MALLOC, VOID_TYPE, fname, lineno);
        memset(aa, 0, tmpii);
        //call_check(aa, tmpii, fname, lineno);
        return aa;
}

// size_t est défini comme un entier long non signé (unsigned long)
char *local_my_realloc(char *aa, size_t size, char fname[], int lineno)
{
        //remove_ptr(aa, fname, lineno);
        unsigned long tmpjj = 0;
        if (aa) // aa !=  NULL
                tmpjj = strlen(aa);
        unsigned long tmpqq = size + SAFE_MEM;
        size_t  tmpii = sizeof (char) * (tmpqq);
        aa = (char *) realloc(aa, tmpii);
        if (aa == NULL)
                raise_error_exit(REALLOC, CHAR_TYPE, fname, lineno);

        // ne pas utiliser memset ! memset(aa, 0, tmpii);
        aa[tmpqq-1] = 0;
        unsigned long kk = tmpjj;
        if (tmpjj > tmpqq)
                kk = tmpqq;
        for ( ; kk < tmpqq; kk++)
                aa[kk] = 0;
        //call_check(aa, tmpii, fname, lineno);
        return aa;
}

// size_t est défini comme un entier long non signé (unsigned long)
short *local_my_realloc(short *aa, size_t size, char fname[], int lineno)
{
        //remove_ptr(aa, fname, lineno);
        unsigned long tmpqq = size + SAFE_MEM;
        size_t  tmpii = sizeof (short) * (tmpqq);
        aa = (short *) realloc(aa, tmpii);
        if (aa == NULL)
                raise_error_exit(REALLOC, CHAR_TYPE, fname, lineno);
        // ne pas utiliser memset ! memset(aa, 0, tmpii);
        // pas pour les nombres ! aa[tmpqq-1] = 0;
        //call_check(aa, tmpii, fname, lineno);
        return aa;
}

// size_t est défini comme un entier long non signé (unsigned long)
int *local_my_realloc(int *aa, size_t size, char fname[], int lineno)
{
        //remove_ptr(aa, fname, lineno);
        unsigned long tmpqq = size + SAFE_MEM;
        size_t  tmpii = sizeof (int) * (tmpqq);
        aa = (int *) realloc(aa, tmpii);
        if (aa == NULL)
                raise_error_exit(REALLOC, CHAR_TYPE, fname, lineno);
        // ne pas utiliser memset ! memset(aa, 0, tmpii);
        // pas pour les nombres ! aa[tmpqq-1] = 0;
        //call_check(aa, tmpii, fname, lineno);
        return aa;
}

// size_t est défini comme un entier long non signé (unsigned long)
long *local_my_realloc(long *aa, size_t size, char fname[], int lineno)
{
        //remove_ptr(aa, fname, lineno);
        unsigned long tmpqq = size + SAFE_MEM;
        size_t  tmpii = sizeof (long) * (tmpqq);
        aa = (long *) realloc(aa, tmpii);
        if (aa == NULL)
                raise_error_exit(REALLOC, CHAR_TYPE, fname, lineno);
        // ne pas utiliser memset ! memset(aa, 0, tmpii);
        // pas pour les nombres ! aa[tmpqq-1] = 0;
        //call_check(aa, tmpii, fname, lineno);
        return aa;
}

// size_t est défini comme un entier long non signé (unsigned long)
float *local_my_realloc(float *aa, size_t size, char fname[], int lineno)
{
        //remove_ptr(aa, fname, lineno);
        unsigned long tmpqq = size + SAFE_MEM;
        size_t  tmpii = sizeof (float) * (tmpqq);
        aa = (float *) realloc(aa, tmpii);
        if (aa == NULL)
                raise_error_exit(REALLOC, CHAR_TYPE, fname, lineno);
        // ne pas utiliser memset ! memset(aa, 0, tmpii);
        // pas pour les nombres ! aa[tmpqq-1] = 0;
        //call_check(aa, tmpii, fname, lineno);
        return aa;
}

// size_t est défini comme un entier long non signé (unsigned long)
double *local_my_realloc(double *aa, size_t size, char fname[], int lineno)
{
        //remove_ptr(aa, fname, lineno);
        unsigned long tmpqq = size + SAFE_MEM;
        size_t  tmpii = sizeof (double) * (tmpqq);
        aa = (double *) realloc(aa, tmpii);
        if (aa == NULL)
                raise_error_exit(REALLOC, CHAR_TYPE, fname, lineno);
        // ne pas utiliser memset ! memset(aa, 0, tmpii);
        // pas pour les nombres ! aa[tmpqq-1] = 0;
        //call_check(aa, tmpii, fname, lineno);
        return aa;
}

static void raise_error_exit(short mtype, short datatype, char fname[], int lineno)
{
        if (mtype == MALLOC)
        {
                fprintf(stdout, "\nFatal Error: malloc() failed!!");
                fprintf(stderr, "\nFatal Error: malloc() failed!!");
        }
        else
        if (mtype == REALLOC)
        {
                fprintf(stdout, "\nFatal Error: realloc() failed!!");
                fprintf(stderr, "\nFatal Error: realloc() failed!!");
        }
        else
        {
                fprintf(stdout, "\nFatal Error: mtype not supplied!!");
                fprintf(stderr, "\nFatal Error: mtype not supplied!!");
                exit(-1);
        }

        // Récupère la date et l'heure courantes et les met dans le fichier d'erreurs...
        char date_str[DATE_MAX_SIZE + SAFE_MEM];
        time_t tt;
        tt = time(NULL);
        struct tm *ct = NULL;
        ct = localtime(& tt); // time() in secs since Epoch 1 Jan 1970
        if (ct == NULL)
        {
                fprintf(stdout, "\nWarning: Could not find the local time, localtime() failed\n");
                fprintf(stderr, "\nWarning: Could not find the local time, localtime() failed\n");
        }
        else
                strftime(date_str, DATE_MAX_SIZE , "%C", ct);

        FILE *ferr = NULL;
        char    filename[100];
        strcpy(filename, LOG_FILE);
        ferr = fopen(filename, "a");
        if (ferr == NULL)
        {
                fprintf(stdout, "\nWarning: Cannot open file %s\n", filename);
                fprintf(stderr, "\nWarning: Cannot open file %s\n", filename);
        }
        else
        {
                // **************************************************
                // **** Fait le putenv dans la fonction main()  *****
                //              char p_name[1024];
                //              sprintf(p_name, "PROGRAM_NAME=%s", argv[0]);
                //              putenv(p_name);
                // **************************************************
                char    program_name[200+SAFE_MEM];
                if (getenv("PROGRAM_NAME") == NULL)
                {
                        fprintf(ferr, "\n%sWarning: You did not putenv() PROGRAM_NAME env variable in main() function\n", 
                                        date_str);
                        program_name[0] = 0;
                }
                else
                        strncpy(program_name, getenv("PROGRAM_NAME"), 200);

                if (mtype == MALLOC)
                        fprintf(ferr, "\n%s: %s - Fatal Error - my_malloc() failed.", date_str, program_name);
                else
                if (mtype == REALLOC)
                {
                        fprintf(ferr, "\n%s: %s - Fatal Error - my_realloc() failed.", date_str, program_name);
                        char dtype[50];
                        switch(datatype)
                        {
                                case VOID_TYPE:
                                        strcpy(dtype, "char*");
                                        break;
                                case CHAR_TYPE:
                                        strcpy(dtype, "char*");
                                        break;
                                case SHORT_TYPE:
                                        strcpy(dtype, "char*");
                                        break;
                                case INT_TYPE:
                                        strcpy(dtype, "char*");
                                        break;
                                case LONG_TYPE:
                                        strcpy(dtype, "char*");
                                        break;
                                case FLOAT_TYPE:
                                        strcpy(dtype, "char*");
                                        break;
                                case DOUBLE_TYPE:
                                        strcpy(dtype, "char*");
                                        break;
                                default:
                                        strcpy(dtype, "none*");
                                        break;
                        }
                        fprintf(ferr, "\n%s %s - Fatal Error: %s realloc() failed!!", date_str, program_name, dtype);
                }

                fprintf(ferr, "\n%s %s - Very severe error condition. Exiting application now....", 
                                        date_str, program_name);
                fclose(ferr);
        }

        exit(-1);
}

// /////////////////////////////////////////////////////////////
//              Fonctions pour afficher la mémoire totale utilisée
//              Ces fonctions peuvent être utilisées pour déboguer
//              Devraient être commentées pour le code de production
// Utilisation de ces fonctions :
//              Dans votre fonction main(), mettre les lignes 
//                      char p_name[1024];
//                      sprintf(p_name, "PROGRAM_NAME=%s", argv[0]);
//                      putenv(p_name);
//                      print_total_memsize(); // au debut
//                      ......
//                      ......
//                      print_total_memsize(); // à la fin
// /////////////////////////////////////////////////////////////

// *********************************************************
// ** Les fonctions ci-dessus utilisent le conteneur list de la STL.
// ** Pour plus d'aide sur les listes, voir
// **   http://www.sgi.com/Technology/STL and List.html
// **   http://www.sgi.com/Technology/STL and other_resources.html
// **   http://www.halpernwightsoftware.com/stdlib-scratch/quickref.html
// *********************************************************
/*
#ifndef DEBUG
void local_print_total_memsize(char *fname, int lineno)
{
        // Cette fonction est disponible dans les 2 modes débogage ou non-débogage...
}
#endif  //------------> si DEBUG n'est pas défini
#ifdef DEBUG
class MemCheck
{
        public:
                MemCheck(void *aptr, size_t amem_size, char fname[], int lineno);
                void    *ptr;
                size_t  mem_size;
                static  list<MemCheck>               mcH;  // tete de la liste
                static  unsigned long           total_memsize;  // memore totale allouee
};

// Variables globales
list<MemCheck>               MemCheck::mcH;
unsigned long           MemCheck::total_memsize = 0;

MemCheck::MemCheck(void *aptr, size_t amem_size, char fname[], int lineno)
{
        char func_name[100];
        FILE    *ferr = NULL;
        sprintf(func_name, "MemCheck() - File: %s Line: %d", fname, lineno);

        ferr = fopen(LOG_FILE, "a");
        if (ferr == NULL)
        {
                fprintf(stdout, "\nWarning: Cannot open file %s\n", LOG_FILE);
                fprintf(stderr, "\nWarning: Cannot open file %s\n", LOG_FILE);
                #ifdef DEBUG_MEM
                        exit(-1);
                #else
                        return;
                #endif
        }

        // Cherche si le pointeur existe déjà dans la liste...
        bool does_exist = false;
        list<MemCheck>::iterator iter1; // voir include/g++/stl_list.h
        //fprintf(ferr, "\n%s Before checking.. !!\n", func_name);
        list<MemCheck>::size_type sztype; // voir include/g++/stl_list.h

        // Le pointeur aptr n'existe pas dans la liste, alors on l'ajoute...
        //if (MemCheck::mcH.size() == 0)
        if (sztype == 0)
        {
                //fprintf(ferr, "\n%s aptr Not found\n", func_name);
                ptr = aptr;
                mem_size = amem_size;
                MemCheck::total_memsize += amem_size;

                // Voir aussi push_front(), list(), list(n), list(n, T)
                MemCheck tmpck = *this;
                MemCheck::mcH.push_back(tmpck);

                //MemCheck::mcH.insert(MemCheck::mcH.begin(), tmpck);
                //MemCheck::mcH.insert(MemCheck::mcH.end(), *this);
                fprintf(ferr, "\n%s sztype is %d\n", func_name, sztype);
                return;
        }
        if (MemCheck::mcH.empty() ) //if (MemCheck::mcH.empty() == true )
        {
                //fprintf(ferr, "\n%s List is empty!!\n", func_name);
        }
        for (iter1 = MemCheck::mcH.begin(); iter1 != MemCheck::mcH.end(); iter1++)
        {
                if (iter1 == NULL)
                {
                        fprintf(ferr, "\n%s Iterator iter1 is NULL!!\n", func_name);
                        break;
                }
                if ( ((*iter1).ptr) == aptr)
                {
                        does_exist = true;
                        fprintf(ferr, "\n%s Already exists!!\n", func_name);
                        fprintf(ferr, "\n%s Fatal Error exiting now ....!!\n", func_name);
                        #ifdef DEBUG_MEM
                                exit(-1); //------------------------------------------------------------------>>>
                        #else
                                return;
                        #endif
                        // Change la taille de la mémoire pour de nouvelles valeurs
                        // Pour la taille totale - supprimer l'ancienne taille et ajouter la nouvelle
                        //fprintf(ferr, "\n%s total_memsize = %lu\n", func_name, (*iter1).total_memsize);
                        //fprintf(ferr, "\n%s mem_size = %u\n", func_name, (*iter1).mem_size);
                        //fprintf(ferr, "\n%s amem_size = %u\n", func_name, amem_size);
                        (*iter1).total_memsize = (*iter1).total_memsize + amem_size;
                        if ((*iter1).total_memsize > 0 )
                        {
                                if ((*iter1).total_memsize >= (*iter1).mem_size )
                                        (*iter1).total_memsize = (*iter1).total_memsize - (*iter1).mem_size;
                                else
                                {
                                        fprintf(ferr, "\n\n%s total_memsize is less than mem_size!!", func_name);
                                        fprintf(ferr, "\n%s total_memsize = %lu", func_name, (*iter1).total_memsize);
                                        fprintf(ferr, "\n%s mem_size = %u", func_name, (*iter1).mem_size);
                                        fprintf(ferr, "\n%s amem_size = %u\n", func_name, amem_size);
                                }
                        }
                        (*iter1).mem_size = amem_size;
                }
        }

        // Le pointeur aptr n'existe pas dans la liste, alors on l'ajoute maintenant
        if (does_exist == false)
        {
                //fprintf(ferr, "\n%s aptr Not found\n", func_name);
                ptr = aptr;
                mem_size = amem_size;
                MemCheck::total_memsize += amem_size;
                MemCheck::mcH.insert(MemCheck::mcH.end(), *this);
        }
        fclose(ferr);
}

static inline void call_check(void *aa, size_t tmpii, char fname[], int lineno)
{
        MemCheck bb(aa, tmpii, fname, lineno);
        if (& bb);  // une instruction inutile pour éviter un avertissement du compilateur
}

static inline void remove_ptr(void *aa, char fname[], int lineno)
{
        char    func_name[100];
        if (aa == NULL)
                return;

        sprintf(func_name, "remove_ptr() - File: %s Line: %d", fname, lineno);
        FILE *ferr = NULL;
        ferr = fopen(LOG_FILE, "a");
        if (ferr == NULL)
        {
                fprintf(stdout, "\nWarning: Cannot open file %s\n", LOG_FILE);
                fprintf(stderr, "\nWarning: Cannot open file %s\n", LOG_FILE);
                #ifdef DEBUG_MEM
                        exit(-1);
                #else
                        return;
                #endif
        }

        bool does_exist = false;
        if (MemCheck::mcH.empty() == true)
        {
                //fprintf(ferr, "\n%s List is empty!!\n", func_name);
                //fclose(ferr);
                //return;
        }
        list<MemCheck>::iterator iter1; // see file include/g++/stl_list.h
        for (iter1 = MemCheck::mcH.begin(); iter1 != MemCheck::mcH.end(); iter1++)
        {
                if (iter1 == NULL)
                {
                        fprintf(ferr, "\n%s Iterator iter1 is NULL!!\n", func_name);
                        break;
                }
                if ( ((*iter1).ptr) == aa)
                {
                        does_exist = true;
                        // Change la taille de la mémoire pour les nouvelles valeurs
                        // Pour la taille totale - supprimer l'ancienne taille
                        //fprintf(ferr, "\n%s total_memsize = %lu\n", func_name, (*iter1).total_memsize);
                        //fprintf(ferr, "\n%s mem_size = %u\n", func_name, (*iter1).mem_size);
                        if ((*iter1).total_memsize > 0 )
                        {
                                if ((*iter1).total_memsize >= (*iter1).mem_size )
                                        (*iter1).total_memsize = (*iter1).total_memsize - (*iter1).mem_size;
                                else
                                {
                                        fprintf(ferr, "\n\n%s total_memsize is less than mem_size!!", func_name);
                                        fprintf(ferr, "\n%s total_memsize = %lu", func_name, (*iter1).total_memsize);
                                        fprintf(ferr, "\n%s mem_size = %u\n", func_name, (*iter1).mem_size);
                                }
                        }
                        MemCheck::mcH.erase(iter1);
                        break;  // break pour éviter une boucle infinie
                }
        }
        if (does_exist == false)
        {
                //fprintf(ferr, "\n%s Fatal Error: - You did not allocate memory!! \n", func_name);
                //fprintf(ferr, "\n%s The value passed is %s\n", func_name, (char *) aa);
        }
        else
                //fprintf(ferr, "\n%s found\n", func_name);
        fclose(ferr);
}

static inline void call_free_check(void *aa, char *fname, int lineno)
{
        char func_name[100];
        sprintf(func_name, "call_free_check() - File: %s Line: %d", fname, lineno);

        FILE *ferr = NULL;
        ferr = fopen(LOG_FILE, "a");
        if (ferr == NULL)
        {
                fprintf(stdout, "\nWarning: Cannot open file %s\n", LOG_FILE);
                fprintf(stderr, "\nWarning: Cannot open file %s\n", LOG_FILE);
                #ifdef DEBUG_MEM
                        exit(-1);
                #else
                        return;
                #endif
        }

        bool does_exist = false;
        list<MemCheck>::iterator iter1; // voir include/g++/stl_list.h
        for (iter1 = MemCheck::mcH.begin(); iter1 != MemCheck::mcH.end(); iter1++)
        {
                if (iter1 == NULL)
                {
                        fprintf(ferr, "\n%s Iterator iter1 is NULL!!\n", func_name);
                        break;
                }
                if ( ((*iter1).ptr) == aa)
                {
                        does_exist = true;
                        //fprintf(ferr, "\n%s iter1.mem_size = %u\n", func_name, (*iter1).mem_size);
                        //fprintf(ferr, "\n%s Total memory allocated = %lu\n",  func_name, (*iter1).total_memsize);
                        if ((*iter1).total_memsize > 0 )
                        {
                                if ((*iter1).total_memsize >= (*iter1).mem_size )
                                        (*iter1).total_memsize = (*iter1).total_memsize - (*iter1).mem_size;
                                else
                                {
                                        fprintf(ferr, "\n\n%s total_memsize is less than mem_size!!", func_name);
                                        fprintf(ferr, "\n%s total_memsize = %lu", func_name, (*iter1).total_memsize);
                                        fprintf(ferr, "\n%s mem_size = %u", func_name, (*iter1).mem_size);
                                }
                        }
                        MemCheck::mcH.erase(iter1);
                        break;  // break pour éviter une boucle infinie
                }
        }
        if (does_exist == false)
        {
                fprintf(ferr, "\n%s Fatal Error: free() - You did not allocate memory!!\n",
                                func_name);
                //fprintf(ferr, "\n%s The value passed is %s\n", func_name, (char *) aa);
                fclose(ferr);
                #ifdef DEBUG_MEM
                        exit(-1);
                #else
                        return;
                #endif
        }
        else
        {
                //fprintf(ferr, "\n%s found\n", func_name);
        }
        fclose(ferr);
}

void local_print_total_memsize(char *fname, int lineno)
{
        char func_name[100];
        sprintf(func_name, "local_print_total_memsize() - %s Line: %d", fname, lineno);

        FILE *ferr = NULL;
        ferr = fopen(LOG_FILE, "a");
        if (ferr == NULL)
        {
                fprintf(stdout, "\nWarning: Cannot open file %s\n", LOG_FILE);
                fprintf(stderr, "\nWarning: Cannot open file %s\n", LOG_FILE);
                #ifdef DEBUG_MEM
                        exit(-1);
                #else
                        return;
                #endif
        }

        fprintf(ferr, "\n%s Total memory MemCheck::total_memsize = %lu\n",  func_name, MemCheck::total_memsize);
        fclose(ferr);
}
#endif  //------------> si DEBUG est défini
*/


Page suivante Page précédente Table des matières