heap analysis

I read the heap analysis document but couldn’t find how to
deal with the new operator.

In QNX4 I used to replace all malloc and free with a debug
version. mem_malloc and mem_free. These were macros
that passed function and line number information. Very
usefull to detect memory leak as any unfreed block would
contain a reference to the function and line number of the
corresponding mem_malloc.

I can’t get this to work using new/delete as I couldn’t find
a way to replace them with macro. I overloaded new
and delete that in turn called malloc but I have no way
to get line and function information to the overloaded new.

Any idea?

  • Mario

“People looking to serious, should be looking to Sirius”

In article <9321dr$kjc$1@nntp.qnx.com>,
Mario Charest <mcharest@void_zinformatic.com> wrote:

I read the heap analysis document but couldn’t find how to
deal with the new operator.

In QNX4 I used to replace all malloc and free with a debug
version. mem_malloc and mem_free. These were macros
that passed function and line number information. Very
usefull to detect memory leak as any unfreed block would
contain a reference to the function and line number of the
corresponding mem_malloc.

I can’t get this to work using new/delete as I couldn’t find
a way to replace them with macro. I overloaded new
and delete that in turn called malloc but I have no way
to get line and function information to the overloaded new.

Any idea?

Yes. I didn’t go to the effort of providing all of the support
necessary for doing complete C++ support in the way that it is
done for C. In fact, the (checked) smart pointer template for C++ pointers
is as far as I went. However, you can get C++ to provide the
same level of information, but a macro is not necessarily the advised way
to do it.

With a default new operator – which is the one I assume you overloaded –
you could only get the return address of the caller. This works fine
in most cases, and is what the malloc_g library gives you if you
simply link against the library without modifying the application – apart
from dumping the heap on exit or whenever it is you want to detect leaks.

The malloc in the debug library does this in the following way:

void *
malloc(size_t size)
{
int line = (int)__build_return_address(0);
return debug_malloc(NULL, line, size);
}

Therefore, you can have the default new operator do the same thing
and get the program counter at the point of the leak. If you wanted
to change code you could also define a NEW macro, but there would be
no way to pass the file and line information to the new operator since
it only takes a size_t parameter.

The only way you could associate the file and line with a previously allocated
block is to find the block header and break
encapsulation by inserting the new file and line information in the
debugging part of the header – assuming you have compiled with the
malloc_g header files and linked against malloc_g. To be on the safe
side, you should call _mptr(this) to find the start of the block,
cast it to a (Dhead *) and subtract one to find the start of the
header.

i.e. inside the NEW(T,params) macro:

T *bp = new (params);
Dhead *hp = (Dhead *)_mptr(bp);
hp–;
hp->d_debug.callerpc_line = LINE;
hp->d_debug.file = FILE;

Of course, because you need a block and a return value, you need to
use a GCC extension to make the macro an expression.

Failing that, you could acquire a mutex inside the macro, set global
file and line variables, and use those in the new operator. Not very
pretty, but not as ugly as, say, pushing them on the stack and unwinding
the stack in the new operator to find them – which is an ugly possibility.

Happily, there is a better way if you compile -g and keep the symbol
information. It won’t give you file and line information, but it is
close. Include dlfcn.h in the module with the new operator
and do the following to obtain the information:

void *ptr;
void *pc = (void *)__builtin_return_address(0);
Dl_info dli;

if (dladdr(pc, &dli)) {
ptr = debug_malloc(dli.dli_sname, pc-dli.dli_saddr, size);
}

This would give you a symbol and an offset. Either this, or the caller
return address is more than adequate when you run the program in GDB,
because you can just list the given address to see the line.




  • Mario

“People looking to serious, should be looking to Sirius”
\

Steve Furr email: furr@qnx.com
QNX Software Systems, Ltd.

In article <932ag0$pi6$1@nntp.qnx.com>, Steve Furr <furr@qnx.com> wrote:

In article <9321dr$kjc$> 1@nntp.qnx.com> >,
Mario Charest <mcharest@void_zinformatic.com> wrote:


I read the heap analysis document but couldn’t find how to
deal with the new operator.

In QNX4 I used to replace all malloc and free with a debug
version. mem_malloc and mem_free. These were macros
that passed function and line number information. Very
usefull to detect memory leak as any unfreed block would
contain a reference to the function and line number of the
corresponding mem_malloc.

I can’t get this to work using new/delete as I couldn’t find
a way to replace them with macro. I overloaded new
and delete that in turn called malloc but I have no way
to get line and function information to the overloaded new.

Any idea?

Yes. I didn’t go to the effort of providing all of the support
necessary for doing complete C++ support in the way that it is
done for C. In fact, the (checked) smart pointer template for C++ pointers
is as far as I went. However, you can get C++ to provide the
same level of information, but a macro is not necessarily the advised way
to do it.

Maybe as preface to this I should restate the obvious. The malloc_g
library described in the document keeps track of file and line
information for the block allocation, just as you used to do.

When the debug_malloc entry point isn’t used directly, the library stores
the caller’s return address in the line information, so you will get that
when malloc_g reports a leak.

The malloc_g will automatically detect memory leaks whenever you ask
it to scan the heap. This is done with a call to malloc_dump.
The two parameters are the file descriptor to which to direct the output
and a boolean indicating whether (true) to abort if the heap is corrupted.
(Caveat: the first few reported items are usually false hits to blocks
created in the C startup routines, to which malloc_g can’t find the roots).

Steve Furr email: furr@qnx.com
QNX Software Systems, Ltd.

The malloc in the debug library does this in the following way:

void *
malloc(size_t size)
{
int line = (int)__build_return_address(0);
return debug_malloc(NULL, line, size);
}

Problem is this would not work with QNX4. I could
try to write build_return_address but that would be nasty
since it would affected by how it was compile -3r versus -3s.

However you gave very valueable information ( nice subject
of an article )

“Mario Charest” <mcharest@void_zinformatic.com> wrote in message
news:932bus$q65$1@nntp.qnx.com

The malloc in the debug library does this in the following way:

void *
malloc(size_t size)
{
int line = (int)__build_return_address(0);
return debug_malloc(NULL, line, size);
}


Problem is this would not work with QNX4. I could
try to write build_return_address but that would be nasty
since it would affected by how it was compile -3r versus -3s.

I solve the problem by writting new in assembly (under QNX4).
Was a bit tricky because of name mangling, but seems to be working so far.

However you gave very valueable information ( nice subject
of an article )

You could use the placement new operator and a new macro:

// ----- Some header
void operator new (size_t size, const char file);
void *operator new[] (size_t size, const char *file);

#define new
new (FILE)
#endif

// ---- Implemented as:
void operator new (size_t size, const char file)
{
return debug_malloc(file, 0, file);
}

void *operator new[] (size_t size, const char *file)
{
return debug_malloc (file, 0, size);
}

“Mario Charest” <mcharest@void_zinformatic.com> wrote in message
news:9321dr$kjc$1@nntp.qnx.com

I read the heap analysis document but couldn’t find how to
deal with the new operator.

In QNX4 I used to replace all malloc and free with a debug
version. mem_malloc and mem_free. These were macros
that passed function and line number information. Very
usefull to detect memory leak as any unfreed block would
contain a reference to the function and line number of the
corresponding mem_malloc.

I can’t get this to work using new/delete as I couldn’t find
a way to replace them with macro. I overloaded new
and delete that in turn called malloc but I have no way
to get line and function information to the overloaded new.

Any idea?

  • Mario

“People looking to serious, should be looking to Sirius”