Debug memory allocation with STL

R

Riadh Elloumi

Hi,

I have some problems when debugging memory allocation (for both malloc
and new) in a program that uses standard lists and vectors. When I add
an element to the vector, the overloaded "delete" operator is called
somewhere in the STL library and it cannot find the allocated memory.
How can I avoid this problem ? Can I overload new and delete only in my
code and not in the STL?

You can see my problem by compiling the mem.cpp joined file:

g++ -g -Wall -lpthread -o mem mem.cpp

Then debug it by gdb

gdb mem

gdb> run

Examine the stack. It's curious that the problem happen at k = 64

int main ()
{
vector<A> va;

for (int k = 0; k < 10000; k ++)
va.push_back(A());

int* i = new int;
delete i;

return 0;

}

I think that the STL allocates 64 entries by default in the vector and
if that isn't enough, it frees and allocates memory for that task.
Unfortunately, this interfere with my memory debugger.

Thank you for your help,

Riadh.

#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <assert.h>
#include <pthread.h>
#include <list>
#include <string>
#include <vector>
#include <map>

using std::vector;
using std::string;
using std::list;
using std::map;
using std::pair;

#define MMAX 1024

typedef struct {
void* address;
char* file;
int line;
char* function;
} MINFO;


void *xmalloc_(int, const char*, int);
void xfree_(void *, const char*, int);
#define xmalloc(size) xmalloc_(size, __FILE__,__LINE__)
#define xfree(ptr) xfree_(ptr, __FILE__,__LINE__)
#define xrealloc(ptr,newsize) xrealloc_(ptr, newsize, __FILE__,__LINE__)
#define header_new() header_new_(__FILE__,__LINE__)
inline void * operator new(size_t size, const char *file, int line)
{
return xmalloc_(size, file, line);
}
inline void operator delete(void *ptr)
{
xfree_(ptr, NULL, 0);
}
#define new new(__FILE__, __LINE__)

// src

int mstart;
MINFO marray[2][MMAX];
pthread_rwlock_t mlock;


void marray_add(void* ptr, const char* file, int line)
{
int i = 0;

while (i < MMAX) {
if (marray[mstart].address == 0)
break;
i++;
}

if (i == MMAX) {
printf("Malloc debugger: too many allocated pointers");
abort();
}

marray[mstart].address = ptr;
marray[mstart].file = strdup(file);
marray[mstart].line = line;
marray[mstart].function = 0;
}

void marray_delete(void* ptr, const char* file, int line)
{
int i = 0, j;

for (j = 0; j < 2; j++)
for (i = 0; i < MMAX; i++) {
if (marray[j].address == ptr)
goto add_adress_found;
}

/* adress was not found */
printf("Malloc debugger: free a wrong address");
abort();
return;


add_adress_found:

marray[j].address = 0;
free(marray[j].file);
marray[j].file = 0;
marray[j].line = 0;
marray[j].function = 0;
}

void marray_replace(void* ptr, void* newptr, char* file, int line)
{
int i = 0, j;

for (j = 0; j < 2; j++)
for (i = 0; i < MMAX; i++) {
if (marray[j].address == ptr)
goto replace_adress_found;
}

/* adress was not found */
printf("Malloc debugger: realloc with a wrong address!");
abort();

replace_adress_found:

free(marray[j].file);

marray[j].address = newptr;
marray[j].file = strdup(file);
marray[j].line = line;
marray[j].function = 0;
}

void *xmalloc_(int size, const char* file, int line)
{
void *ret;

assert(size > 0);

ret = malloc(size);

assert(ret);

pthread_rwlock_wrlock(&mlock);

marray_add(ret, file, line);

pthread_rwlock_unlock(&mlock);

return ret;
}

void xfree_(void *ptr, const char* file, int line)
{
assert(ptr);

pthread_rwlock_wrlock(&mlock);

marray_delete(ptr, file, line);

pthread_rwlock_unlock(&mlock);

free(ptr);

}

void *xrealloc_(void *ptr, int newsize, char* file, int line)
{
void *newptr;

assert(newsize > 0);

newptr = realloc(ptr, newsize);

assert(newptr);

pthread_rwlock_wrlock(&mlock);

if (ptr == NULL) {
/* equivalent to malloc */
marray_add(newptr, file, line);
} else {
marray_replace(ptr, newptr, file, line);
}
pthread_rwlock_unlock(&mlock);

return newptr;
}

class A {
int abc;

public:
A();
};

A::A()
{
abc = 0;
}

int main ()
{
vector<A> va;

for (int k = 0; k < 10000; k ++)
va.push_back(A());

int* i = new int;
delete i;

return 0;

}
 
T

tom_usenet

Hi,

I have some problems when debugging memory allocation (for both malloc
and new) in a program that uses standard lists and vectors. When I add
an element to the vector, the overloaded "delete" operator is called
somewhere in the STL library and it cannot find the allocated memory.
How can I avoid this problem ? Can I overload new and delete only in my
code and not in the STL?

Not very easily. You can of course use a custom allocator for the STL,
but this effects all of your container declarations. Some libraries
(STLport and SGI for two) let you configure the implementation of
std::allocator, giving you the option of using malloc rather than
operator new. Consult your library allocator documentation to see
whether this is an option.

The easiest solution is probably to override the operator new used by
other code - just provide an overload of the normal global operator
new:

void* operator new(std::size_t size)
{
return xmalloc_(size, "library allocation", 0);
}

or similar. Now your operator delete override will correctly free that
memory too.

Part of your problem mostly comes from redefining new with a macro,
which is of course illegal (MFC makes the same mistake IIRC). It
prevents use of placement new, etc. It requires that you #include your
debug alloc header after anything that might use new (such as standard
library headers). You might be better off replacing "new" with
something like "MYNEW" (which won't interact with anything other your
own code).

Tom

C++ FAQ: http://www.parashift.com/c++-faq-lite/
C FAQ: http://www.eskimo.com/~scs/C-faq/top.html
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,755
Messages
2,569,536
Members
45,007
Latest member
obedient dusk

Latest Threads

Top