Andrei Ciobanu
Andrei Ciobanu

Reputation: 12838

How do I mock memory allocation failures?

I want to extensively test some pieces of C code for memory leaks.

On my machine I have 4 Gb of RAM, so it's very unlikely for a dynamic memory allocation to fail. Still I want to see the comportment of the code if memory allocation fails, and see if the recover mechanism is "strong" enough.

What do you suggest ? How do I emulate an environment with lower memory specs ? How do i mock my tests ?

EDIT: I want my tests to be code independent. I only have "access" to return values for different functions in the library I am testing. I am not supposed to write "test logic" inside the code I am testing.

Upvotes: 4

Views: 3014

Answers (6)

Pasi Savolainen
Pasi Savolainen

Reputation: 2500

If this is a unix -type of system, then you can do the same thing that jemalloc does. Implement your own malloc, compile it as .so -library and start the test with LD_PRELOAD=yourmalloc.so

You could build in a setting that will allow you to control how it operates:

void tester() {
     your_malloc_allow_allocation(1024*1024*4); // allow 4 more megs of allocation

     librarycall();
     // ... handle errors..

     your_malloc_reset_limits(); // drop limits
}

Upvotes: 3

kriss
kriss

Reputation: 24177

type in *(char*)0; when you want your code to fail or store it in allocated var

(obviously it should be activated/desactivated by some #define setted by makefile)

The idea is to precisely control which malloc you want to fail. I used the previous trick to ensure what would be the behavior of a program I wrote if a segfault ever occured. I was able to check that the exception was caught and that there was no memory leak with allready allocated object.

You can also add some kind of counter to make your alloc return 0 only after a while and check that your code corretly handle this case (and, for instance, correctly free parts of what your program choose to destroy to handle memory starvation).

Upvotes: 1

Brian R. Bondy
Brian R. Bondy

Reputation: 347296

Make a wrapper malloc and free, you can put your own logic there for when it fails and when it doesn't.

Then:

#define malloc(X) (myMalloc(X))
#define free(X) (myFree(X))
#define realloc(X, Y) (myRealloc(X, Y))
#define calloc(X, Y) (myCalloc(X, Y))
#define valloc(X) (myValloc(X))

You can #define and #undef the macros as you want throughout your code.

Upvotes: 7

sbi
sbi

Reputation: 224079

When I had to do this, I made a small program which used up all the memory quickly. Something like this:

// Beware, brain-compiled code ahead: 
#include <stdlib.h>

bool alloc(size_t n)
{
    return NULL != malloc(n);
}

int main()
{
    size_t n = 1;
    for(;;) {
        while( alloc(n) )
            n*=2;
        do
            n/=2;
        while( !alloc(n) );
    }
}

My experience with the NT line of Windows was that, while the OS was rock-solid, just about everything else crashed on me, including the debugger. No fun to work that way.

Upvotes: 1

Lazarus
Lazarus

Reputation: 43084

To do this code independently, I'd suggest using a virtual machine with a much smaller memory setting and running your code within that. Otherwise, you are left with testing on actual systems with smaller memory configurations.

Upvotes: 3

SF.
SF.

Reputation: 14069

disable swap, then at the beginning of your app do while(malloc(1000000));

This will leave the environment with less than 1MB of free memory for the rest of your app to run. Adjust the value for other results.

Upvotes: 0

Related Questions