views:

323

answers:

8

Ok, I know this question seems to have been asked many times on stackoverflow.
but please read

Well the answer for any address is "No you can't" but the question here is to know if a pointer points to a piece of memory allocated with malloc/new.
Actually I think it could be easily implemented overriding malloc/free and keeping track of allocated memory ranges.

Do you know a memory management library providing this specific tool ?
Do you know something for production code ?

--
Valgrind is great, but it is too much instrumentation (slow) and as Will said we don't want to use Valgrind like this (making the soft crash is good enough).
Mudflap is a very good solution, but dedicated to GCC, and sadly, a check does not simply return a boolean (see my answer below).
Note that checking that memory writes are legals is a security issue. So looking for performance is motivated *.

+4  A: 

A proof it probably cannot be usefully done:

char * p1 = malloc(1);
free( p1 );
char * p2 = malloc(1);   // probably allocates same block as first malloc

Now both p1 and p2 point at same memory on heap, but only p2 is valid.

anon
Well philosophically it can be disappointing, but if it ends up p2 points to the same address that p1, p1 is still an address of modifiable memory. So that's fine for me.
Ugo
@Ugo even though both the C and C++ standards say p1 may not be used to access that memory?
anon
Weeeeel maybe p2 is the same address as p1... depends on how your malloc works (running under valgrind will pretty much guarantee `p2 != p1` this is on purpose so you can detect use after free, but good malloc's still may or may not (some of them maintain FIFO queues of recently free'd objects of a certain size, they won't give back p1...))
Spudd86
@Neil the standard does NOT say p2 will be the same address as p1 (it's just somewhat probable) and at that point you're just nit picking because the question was about addresses not particular allocations so if `p1 == p2` then by the definition in the question the answer "p1 is heap alloc'd" is acceptable.
Spudd86
Taking this further: what if, through some arbitrary sequence of events, the address pointed to be the old pointer p1 ends up in the middle of a newly allocated block instead of exactly matching p2? Then p1 could still be said to point at part of the heap, but p1 by itself wouldn't be useful in any reasonable way that I can imagine.
TheUndeadFish
anon
@spudd "the standard does NOT say p2 will be the same address as p1" - I didn't say it did.
anon
Besides the fact that you shouldn't do this or rely on this behavior, I'm not seeing how this answers the question ... Maybe I missed something.
BobbyShaftoe
After free(p1) it is undefined behaviour to even use the value of the pointer, i.e. comparing it with p2 is already UB.
Secure
@BobbyShaftoe: Obviously you wouldn't rely on any of that behavior, but it is possible. It's a demonstration of how an invalid pointer could, by chance, point to something in an allocated block of memory. Since that's possible, it's impossible to tell whether a pointer is valid based on its value. TheUndeadFish's comment is relevant here: a pointer could easily point into something completely different.
David Thornley
Common, pointers are addresses. Not mystical objects keeping souls of their preceding lives. A pointer pointing to allocated memory is valid whatever happend when she was a child.
Ugo
+6  A: 

There's no standard way to do this, but various malloc debugging tools may have a way of doing it. For example, if you use valgrind, you can use VALGRIND_CHECK_MEM_IS_ADDRESSABLE to check this and related things

Chris Dodd
valgrind is awesome.
Daniel Stutzbach
Nice ! I didn't know linking with a library was not standard though ;)
Ugo
@Ugo Arguably, linking with a library is not standard. But that aside, what is in libraries used by tools such as valgrind is definitely non-standard, which is why they are platform specific.
anon
@Neil Why would linking with a library not be standard ?
matias
@matias Neither the C++ nor the C standard really describes such a thing - but that is off the point of this question.
anon
@matias Neither the C++ nor the C standard really describes breadth first search, which means it is arguably not standard.
Ugo
@Ugo -- the library is not necessarily be available on every platform that supports C or C++, so its not "standard"
Chris Dodd
if you're using valgrind, you don't check things are addressable you just let valgrind explode when you have a bug, and you fix it :)
Will
@Ugo: the standard describes the mechanisms used to implement a breadth first search. it does not describe the mechanisms used to implement library functionality. It describes how multiple translation units are turned into one program, but it doesn't describe *any* mechanism* by which separate libraries can be created, or loaded by your application.
jalf
@Neil/jalf/Chris Well you are right linking is not standardized but you are still doing standard c++. Same thing with platform specific code, assigning the video frame buffer address somewhere in your code doesn't make your code non standard it just makes it platform specific.
Ugo
@Ugo: I can easily write a breadth-first search algorithm in standard C++ (C would be a little more difficult, not having STL containers, `std::deque` in particular). valgrind is not necessarily available with a standard C++ platform, and cannot be written in standard C++. Therefore, in any standard C++ implementation I've got breadth-first search, but not necessarily valgrind.
David Thornley
@David you mean std::queue don't you ?
Ugo
@Ugo: I was thinking std::deque at the time, for some reason, but std::queue is a much better choice. Thanks.
David Thornley
A: 

You can use LD_PRELOAD, and wrap malloc inside your own function.

Daniel Băluţă
A: 

Memory allocations have an (virtual) address and a length.

The pointer only contains the address.

If you track the length separately, you can check its contained, e.g.:

int check_contained(const char* src,size_t srclen,const char* sub,size_t sublen) {
   return (sub >= src) && (sub+sublen < src+srclen);
}

Symbian has an AllocLen function, but there's no POSIX nor win32 equivalent.

Will
+1  A: 

You can do this yourself, if performance is not a real issue for your application:

Define MyMalloc(...) and MyFree(...) in which, along with calling malloc/free, you update a (ordered)list of pairs {address -- the result of malloc, blockSize -- the amt of memory requested }. Then when you need to check a pointer p, you look for a pair satisfying: address <= p <= address + blockSize.

Other conditions could/should be checked, if you want to actually use that pointer, this will only tell if an address is in use or not.

Andy
A: 

I did something similar, but can't remember how exactly it was coded and i don't have the code at hand.

But the basic idea was to override the new and delete for a base class. In new a static flag was set (e.g. bool inDynamicAlloc=true). This flag is questioned in the constructor of the base class. When it was true, the object was allocated on the heap, on the stack otherwise.

The constructor resets the flag afterwards.

Hope this helps.

jopa
+1  A: 

Mudflap (for gcc) seems very sweet. You have to compile your soft with but it will check any wrong pointer access (heap/stack/static). It is designed to work for production code with slowdown estimated between x1.5 to x5. You can also disable check at read access for speedup.
User check can be performed using

void __mf_check (void *ptr, __mf_size_t sz, int type, const char *location)

Calling this function results to: nothing, fork to gdb, segv or abort depending on environment parameters.

Ugo
A: 

You could use the same techniques that a conservative garbage collector uses to determine if a pointer-like object points to the heap or not. Indeed you could probably crib the source code from bdwgc itself. This would be a non-trivial task, but it would be something you could control and port as needed. (Much of the porting work has already been done, in fact.)

JUST MY correct OPINION