views:

1328

answers:

9

Possible Duplicates:
How can I get the size of an array from a pointer in C?
Is there any way to determine the size of a C++ array programmatically? And if not, why?

I get a pointer to a chunk of allocated memory out of a C style function. Now, it would be really interesting for debugging purposes to know how big the allocated memory block that this pointer points is.

Is there anything more elegant than provoking an exception by blindly running over its boundaries?

Thanks in advance, Andreas

EDIT:

I use VC++2005 on Windows, and GCC 4.3 on Linux

EDIT2:

I have _msize under VC++2005 Unfortunately it results in an exception in debug mode....

EDIT3:

Well. I have tried the way I described above with the exception, and it works. At least while I am debugging and ensuring that immediately after the call to the library exits I run over the buffer boundaries. Works like a charm.

It just isn't elegant and in no way usable in production code.

+7  A: 

The C runtime library does not provide such a function. Furthermore, deliberately provoking an exception will not tell you how big the block is either.

Usually the way this problem is solved in C is to maintain a separate variable which keeps track of the size of the allocated block. Of course, this is sometimes inconvenient but there's generally no other way to know.

Your C runtime library may provide some heap debug functions that can query allocated blocks (after all, free() needs to know how big the block is), but any of this sort of thing will be nonportable.

Greg Hewgill
+4  A: 

No, and you can't rely on an exception when overrunning its boundaries, unless it's in your implementation's documentation. It's part of the stuff you really don't need to know about to write programs. Dig into your compiler's documentation or source code if you really want to know.

David Thornley
Any particular reason why this was downvoted?
David Thornley
Seems good to me. +1
Brian Agnew
Not downvoted by me, but possibly because malloc and access to malloc'd memory is not known for throwing exceptions, being part of C.
anon
Well it does. And I can request that memory chunk and then go provoke the access violation and it simply works. I do this in c++ as the tag states, so exceptions are thrown.
AndreasT
On Windows, you *might* get a structured exception (Access Violation), since that's how the OS communicates that you've stepped over the line. On Linux, i think the equivalent is a segmentation fault. Whether or not your runtime converts these to C++ exceptions is implementation-dependent.
Shog9
It's also iffy. As you say, on Windows you might get an access violation, and on Linux you might get a segmentation fault. Without actually knowing, I'd suspect that these were caused by the virtual memory manager, and therefore would indicate leaving memory pages rather than allocated memory areas.
David Thornley
@David: right - you could potentially end up in another portion of allocated memory, silently trashing other data-structures (including those used by the memory manager...) or reading bogus data. Dangerous territory...
Shog9
+10  A: 

It's not standard but if your library has a msize() function that will give you the size.

A common solution is to wrap malloc with your own function that logs each request along with the size and resulting memory range, in the release build you can switch back to the 'real' malloc.

Martin Beckett
+1 I did this years ago. It's trivial to implement and very useful
Brian Agnew
I have no access to the source.
AndreasT
But the _msize tip might wirk. Thanks!
AndreasT
Check for a _debug_malloc package. There might be a runtime library to get the malloc information at least in a debug build. In general though you shouldn't design your code assuming this is possible
Martin Beckett
+4  A: 

There is no standard C function to do this. Depending on your platform, there may be a non-portable method - what OS and C library are you using?

Note that provoking an exception is unreliable - there may be other allocations immediately after the chunk you have, and so you might not get an exception until long after you exceed the limits of your current chunk.

bdonlan
+1  A: 

The way to do what you want is to BE the allocator. If you filter all requests, and then record them for debugging purposes, then you can find out what you want when the memory is free'd.

Additionally, you can check at the end of the program to see if all allocated blocks were freed, and if not, list them. An ambitious library of this sort could even take FUNCTION and LINE parameters via a macro to let you know exactly where you are leaking memory.

Finally, Microsoft's MSVCRT provides a a debuggable heap that has many useful tools that you can use in your debug version to find memory problems: http://msdn.microsoft.com/en-us/library/bebs9zyz.aspx

On Linux, you can use valgrind to find many errors. http://valgrind.org/

Christopher
It is not me that allocates the mem, it is a library that I have no source access to.
AndreasT
See Adrian's comment
Matt
+4  A: 

Memory checkers like Valgrind's memcheck and Google's TCMalloc (the heap checker part) keep track of this sort of thing.

You can use TCMalloc to dump a heap profile that shows where things got allocated, or you can just have it check to make sure your heap is the same at two points in program execution using SameHeap().

tgamblin
I will definately check that out.
AndreasT
+3  A: 

If you don't mind sleazy violence for the sake of debugging, you can #define macros to hook calls to malloc and free and pad the first 4 bytes with the size.

To the tune of

void *malloc_hook(size_t size) {
    size += sizeof (size_t);
    void *ptr = malloc(size);
    *(size_t *) ptr = size;
    return ((size_t *) ptr) + 1;
}

void free_hook (void *ptr) {
    ptr = (void *) (((size_t *) ptr) - 1);
    free(ptr);
}

size_t report_size(ptr) {
    return * (((size_t *) ptr) - 1);
}

then

#define malloc(x) malloc_hook(x)

and so on

Aside from alignment issues, this is actually the best way to do it in a portable manner. If you use something more adventurous like dlmalloc you could take advantage of weak linking, but for a PC app this is probably overkill.
Dan Olson
This sounds good too, but I don't have access to the code.
AndreasT
Since I unknowingly answered a duplicate question with an almost identical solution, it must deserve an up-vote!
Clifford
+3  A: 

With gcc and the GNU linker, you can easily wrap malloc

#include <stdlib.h>
#include <stdio.h>


void* __real_malloc(size_t sz);
void* __wrap_malloc(size_t sz)
{
    void *ptr;

    ptr = __real_malloc(sz);
    fprintf(stderr, "malloc of size %d yields pointer %p\n", sz, ptr);

    /* if you wish to save the pointer and the size to a data structure, 
       then remember to add wrap code for calloc, realloc and free */

    return ptr;
}

int main()
{
    char *x;
    x = malloc(103);

    return 0;
}

and compile with

gcc a.c -o a -Wall -Werror -Wl,--wrap=malloc

(Of course, this will also work with c++ code compiled with g++, and with the new operator (through it's mangled name) if you wish.)

In effect, the statically/dynamically loaded library will also use your __wrap_malloc.

Adrian Panasiuk
Really? How is that possible? Will code from some .a or .so file that has no debug info be overwritten by that? If yes: Cool! B)
AndreasT
Weak references. The linker will override the symbol references to malloc for you and point them to the place you specify.
Christopher
Yup, no debugging info needed, any library contains a symbol table for the symbols it provides and for the symbols it needs to get from elsewhere. So you can tell the linker what function to bind with the malloc symbol of your executable.
Adrian Panasiuk
+2  A: 

Partial solution: on Windows you can use the PageHeap to catch a memory access outside the allocated block.

PageHeap is an alternate memory manager present in the Windows kernel (in the NT varieties but nobody should be using any other version nowadays). It takes every allocation in a process and returns a memory block that has its end aligned with the end of a memory page, then it makes the following page unaccessible (no read, no write access). If the program tries to read or write past the end of the block, you'll get an access violation you can catch with your favorite debugger.

How to get it: Download and install the package Debugging Tools for Windows from Microsoft: http://www.microsoft.com/whdc/devtools/debugging/default.mspx

then launch the GFlags utility, go to the 3rd tab and enter the name of your executable, then Hit the key. Check the PageHeap checkbox, click OK and you're good to go.

The last thing: when you're done with debugging, don't ever forget to launch GFlags again, and disable PageHeap for the application. GFlags enters this setting into the Registry (under HKLM\Software\Microsoft\Windows NT\CurrentVersion\Image File Execution Options\), so it is persistent, even across reboots.

Also, be aware that using PageHeap can increase the memory needs of your application tremendously.

LaszloG