C++ valgrind alternative for memory bugs

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Someone asked a question recently on how to catch memory bugs. I don't recall if it was for C or C++.

Below is a VERY lightweight alternative to catch a LIMITED class of memory management bugs, for C++.

Valgrind will catch more bugs than this, but is not available on all platforms. ElectricFence will also catch these kinds of bugs.

The new will make sure memory is set to known garbage to start with. The delete will make sure the memory is cleared to different known garbage. (I didn't use the traditional 0xDEADBEEF, because of the potential for misaligned memory for MemEnd, which can be fatal (SIGBUS) for certain platforms.)

I leave placement-new/delete and nothrow-new/delete as an exercise for the reader.

--Eljay

- - - - - - - - - - - - - - - - - - - - - - - - -

#include <cstdlib>
    // malloc, free

#include <cstring>
    // memset

#include <iostream>
    using std::cerr;
    using std::endl;

#include <new>

struct MemBegin
{
    size_t length;
    char beginMark[8]; // B1 or BA
};

struct MemEnd
{
    char endMark[8]; // E1 or EA
};

void* operator new(size_t s) throw(std::bad_alloc)
{
    const size_t supersize = sizeof(MemBegin) + s + sizeof(MemEnd);
    char* p = (char*)malloc(supersize);

    if(p == NULL)
        throw std::bad_alloc();

memset(p, 0xB1, sizeof(MemBegin)); // B1 for beginning of 1 item
memset(p + sizeof(MemBegin), 0xA1, s); // A1 for alloc 1 item
memset(p + sizeof(MemBegin) + s, 0xE1, sizeof(MemEnd)); // E1 for end of 1 item


(*(MemBegin*)p).length = s;

    return (void*)(p + sizeof(MemBegin));
}

void* operator new[](size_t s) throw(std::bad_alloc)
{
    const size_t supersize = sizeof(MemBegin) + s + sizeof(MemEnd);
    char* p = (char*)malloc(supersize);

    if(p == NULL)
        throw std::bad_alloc();

memset(p, 0xBA, sizeof(MemBegin)); // BA for beginning of array
memset(p + sizeof(MemBegin), 0xAA, s); // AA for alloc array
memset(p + sizeof(MemBegin) + s, 0xEA, sizeof(MemEnd)); // EA for end of array


(*(MemBegin*)p).length = s;

    return (void*)(p + sizeof(MemBegin));
}

static void Verify(char* p, char beginMark, char endMark, char freeMark)
{
    MemBegin* b = (MemBegin*)p;

    if(b->beginMark[0] != beginMark
    || b->beginMark[1] != beginMark
    || b->beginMark[2] != beginMark
    || b->beginMark[3] != beginMark
    || b->beginMark[4] != beginMark
    || b->beginMark[5] != beginMark
    || b->beginMark[6] != beginMark
    || b->beginMark[7] != beginMark
    )
    {
        if(beginMark == (char)0xB1)
            cerr << "BeginMark single item: verification failure!";
        else if(beginMark == (char)0xBA)
            cerr << "BeginMark array: verification failure!";
        else
            cerr << "BeginMark (unexpected): verification failure!";

        // We do not trust this de-allocation!
        return;
    }

MemEnd* e = (MemEnd*)(p + sizeof(MemEnd) + b->length);

    if(e->endMark[0] != endMark
    || e->endMark[1] != endMark
    || e->endMark[2] != endMark
    || e->endMark[3] != endMark
    || e->endMark[4] != endMark
    || e->endMark[5] != endMark
    || e->endMark[6] != endMark
    || e->endMark[7] != endMark
    )
    {
        if(endMark == (char)0xE1)
            cerr << "EndMark single item: verification failure!";
        else if(endMark == (char)0xEA)
            cerr << "EndMark array: verification failure!";
        else
            cerr << "EndMark (unexpected): verification failure!";
        return;
    }

size_t s = sizeof(MemBegin) + b->length + sizeof(MemEnd);

    memset(p, freeMark, s);
}

void operator delete(void* p) throw()
{
    if(p != NULL)
    {
        Verify((char*)p, 0xB1, 0xE1, 0xF1);
        free(p);
    }
}

void operator delete[](void* p) throw()
{
    if(p != NULL)
    {
        Verify((char*)p, 0xBA, 0xEA, 0xFA);
        free(p);
    }
}


[Index of Archives]     [Linux C Programming]     [Linux Kernel]     [eCos]     [Fedora Development]     [Fedora Announce]     [Autoconf]     [The DWARVES Debugging Tools]     [Yosemite Campsites]     [Yosemite News]     [Linux GCC]

  Powered by Linux