How can I detect memory leaks in my C program using DEV C ++?

Question:

I use Dev C ++ version 5.11 and Windows 8.1 operating system, my question is for a program that I develop in C, how can I verify that the program is free of memory leaks or memory leaks? Thanks

Answer:

NOTE

In the comments to the answer, @ JacoboCórdova indicates that some modifications are necessary for it to work.

I guess they are due to the different compilers used.

I include this modification, conveniently marked in leaks.c . In case of problems, DELETE said change.

END OF NOTE

There is a relatively simple way:

You have to create 2 additional files to your project: one header

// leaks.h

#ifndef LEAKS_H
#define LEAKS_H

#include <stddef.h>

// ESTE INCLUDE NO DEBERÍA DE SER NECESARIO.
#include "leaks.c"
// SI HAY PROBLEMAS, ELIMINARLO.

#define malloc( S ) ( my_malloc( (S) ) )
#define calloc( C, S ) ( my_calloc( (C), (S) ) )
#define free( P ) ( my_free( (P) ) )

void *my_malloc( size_t );
void *my_calloc( size_t, size_t );
void my_free( void * );

#endif

and another with some code. Note that, in this file, we did not include the previous leaks.h :

// leaks.c

#include <stdlib.h>

static size_t leaks = 0;

void *my_malloc( size_t s ) {
  ++leaks;
  return malloc( s );
}

void *my_calloc( size_t n, size_t s ) {
  ++leaks;
  return calloc( n, s );
}

void my_free( void *p ) {
  --leaks;
  free( p );
}

size_t leaks_count( void ) {
  return leaks;
}

Now, to use the new feature, you have to include "leaks.h" at the beginning of all the .c files you want to check . Specifically, it must be the last #include "" you have.

And one last modification. In the place where you want to know how you have the number of leaks , for example in the main.c :

// main.c

#include <stdio.h>

#include "leaks.h"
// ESTO ES MUY IMPORTANTE
// LO COLOCAMOS FUERA DE CUALQUIER FUNCIÓN.
// PREFERIBLEMENTE, DESPUES DE LOS #include
size_t leaks_count( void );

int main( void ) {
  char *tmp = malloc( 100 );

  free( tmp );

  printf( "Bloques sin liberar: %zu\n", leaks_count( ) );
  // para Windows
  //printf( "Bloques sin liberar: %Iu\n", leaks_count( ) );
  return 0;
}

As you can see, the idea is to replace the normal function calls with calls to our replacement functions, and do what we have to do there. It is no wonder, but it can give us an idea of ​​how we deal with memory leaks.

Notice we don't override realloc( ) . I leave it as entertainment 😉

NOTE

This proposed implementation only counts the number of times we call malloc( ) and free( ) in our source files . This implies that it is by no means an exhaustive control of what we do.

To obtain more exact data, we have several options:

  1. Use one of the many tools available.
  2. Completely replace the system functions that interest us. That is more complex, but perfectly possible , and it is what these tools do.
  3. Extending our functions my_malloc( ) , my_calloc( ) , … Right now, we hardly do anything. But nothing prevents us from increasing our functionality, returning different things, counting the exact bytes that we are using, contemplating realloc( ) , creating nodes of linked lists of the blocks, including even the name of the exact file in which we make the reservation (using __FILE__ ), …

EDIT

It is very important that we understand one thing: it is possible to have memory leaks even if we do the alloc( ) and free( ) .

We are already getting into low-level stuff, but I think it's important to know.

The memory reserve / release functions are not miraculous ; they are simple functions, and they can add things to what we ask for .

Most, in fact, add things before the address they return to us .

By this, I mean that if we wrongly access pointers returned by malloc( ) and the like, we can corrupt the internal data of the memory system. As a consequence, we can make correct use of these functions, and, even so, leave holes in the memory that can not be recovered (until we close the program).

A little example:

struct mydata_s {
  int algo;
  float otro_algo;
  struct mydata_s *mas_de_algo;
} *ptr;


ptr = (struct mydata_s *)malloc( sizeof( struct mydata_s ) );

( ptr - 1 )->algo = 0;

free( ptr );

The above code accesses a zone just before what was returned by malloc( ) .

There, several things can happen:

  1. Nothing happens (don't see what luck).
  2. We corrupt our own data from a previous malloc( ) .
  3. Operating system error (difficult in the example, but possible).
  4. Failed to call free( ) (the management system noticed).
  5. Memory management system corruption .

At this last point, literally anything can happen. Among other things, we can leave a huge hole in memory that we can never use .

C is famous and feared by the facility offered to manipulate at will the memory. There we have a possible reason for the second. Be very careful what we do with our pointers!

Scroll to Top