Page 1 of 2

IsMemory()

Posted: Mon Nov 13, 2006 8:24 pm
by Rescator
I got no idea if this will work "as is",
anyway I was surprised to see no search hits on "ismemory" on the forum at all, any chance of this being implemented?

Code: Select all

/*
 *  IsMemory() command for PureBasic
 */

#include "MemoryPLUGIN.h"


M_PBFUNCTION int PB_IsMemory(char *Memory)
{
  return HeapValidate(PB_Memory_Heap, 0, Memory);
}

Posted: Mon Nov 13, 2006 8:31 pm
by Rescator
Crap, just noticed in the PSDK that HeapValidate() exist in the NT (4.x/5.x/6.x) kernel only...
Hmm. Sorry Fred... Any other way to make a IsMemory() then?

Posted: Mon Nov 13, 2006 8:31 pm
by Fred
Good code for windows, what about one for linux ? :)

Posted: Mon Nov 13, 2006 8:52 pm
by Rescator
Maybe use HeapSize() instead as that exist on all Windows and the PSDK states:
If the function succeeds, the return value is the size of the allocated memory block, in bytes.

If the function fails, the return value is (SIZE_T) -1. The function does not call SetLastError. An application cannot call GetLastError for extended error information.
Although the "(SIZE_T) -1" is a bit confusing I assume this means it returns -1 on failure or does it mean ($FFFFFFFF)-1 ?

In any case if heapsize return -1 this would mean failure and IsMemory() would be made to return #False, if all is ok IsMemory() would be made to return #True

Currently MemorySize() can't be used to test if memory is valid (debugger throws up an error, and a compiled program crashes)
So cloning MemorySize() naming it IsMemory() and making sure it returns #False or #True rather than crashing should work ok on any windows version, and hopefully Linux and Mac as well or?

Posted: Mon Nov 13, 2006 8:55 pm
by Fred
Unfortunately, it's not possible to do that on linux/mac IIRC.

Posted: Mon Nov 13, 2006 8:59 pm
by Trond
IsMemory() should not be implemented. There's probably other uses for it (or?), but I imagine it being used to check if a pointer is valid.
This is very very bad. Like, seriously bug-bug-buggy bad.

Sooner or later a memory area that was freed will be allocated for something else, and the pointer will look valid even though it's pointing to something else. So even if in your program *Ptr.MyStruct only is set to point to memory areas that resemble MyStruct, you could end up accessing a NotMyStruct area by checking if the memory pointer is valid.

Always use program flow or null pointers to know what is valid and what is not.

Posted: Mon Nov 13, 2006 9:03 pm
by freak
> Although the "(SIZE_T) -1" is a bit confusing I assume this means it returns -1 on failure or does it mean ($FFFFFFFF)-1 ?

The (SIZE_T) is just a type cast. So it is -1 interpreted as a variable of type SIZE_T (still -1 in the PB world)

MemorySize() is a direct wrapper to HeapSize(), so it is the api command actually that crashes, not the PB part. Try:

Code: Select all

Debug HeapSize_(GetProcessHeap_(), 0, 123)
So it is no use for validation either.

The only way to implement this is if PB keeps a list of all allocated memory blocks,
i think this is a bit overkill.

I also agree with Tronds opinion.
Having a memory pointer of which you do not know if it is valid or not is a bug in the program imho. This should not happen.

Posted: Mon Nov 13, 2006 9:17 pm
by Rescator
Good points all around.
Just looked for alternative systems. (malloc, calloc, mmap, etc)
And I stumbled over some notes on OpenBSD, it seems even they now prefer to actually have software "crash" instead (to help enforce better coding habits/more bug squashing).

Oh well. So I guess IsMemory() is a good idea that is also a bad idea. *laughs*

Feel free to lock this thread. (deleting it may cause the question/feature to be asked again as IsMemory is mentioned nowhere else in these forums)

Posted: Mon Nov 13, 2006 9:38 pm
by freak
If you just need to know if accessing a pointer would result in a crash, you can have
a look at the IsBadReadPtr_() and IsBadWritePtr_() API.

It only tells you if you can read or write at the memory location, not if and how it was allocated.
It may still be usefull in some cases.
(The PB debugger uses it to avoid a crash if you enter wrong numbers in the MemoryViewer for example.)

Posted: Mon Nov 13, 2006 9:52 pm
by Rescator
A cool, didn't know that... (I wonder how many hook coders remember to use those two? heh)

Posted: Mon Nov 13, 2006 10:52 pm
by Konne
Trond wrote:IsMemory() should not be implemented. There's probably other uses for it (or?), but I imagine it being used to check if a pointer is valid.
This is very very bad. Like, seriously bug-bug-buggy bad.

Sooner or later a memory area that was freed will be allocated for something else, and the pointer will look valid even though it's pointing to something else. So even if in your program *Ptr.MyStruct only is set to point to memory areas that resemble MyStruct, you could end up accessing a NotMyStruct area by checking if the memory pointer is valid.

Always use program flow or null pointers to know what is valid and what is not.
But that's the same with IsWindow/Gadget/Image etc.

Posted: Mon Nov 13, 2006 11:11 pm
by netmaestro
But that's the same with IsWindow/Gadget/Image etc.
Not quite as you can run into timing issues using callbacks where the order and timing of create/destroy for windows and gadgets can cause your code to try to work with a non-valid object. I often use If IsGadget() in my callbacks before affecting code to them and consider it a good coding practice. Perhaps I'm being too careful, but I don't think so. Images are another matter altogether as you must always be able to verify the successful loading/catching of images before trying to work with them. You can't just call LoadImage() and assume it's there and valid.

Posted: Tue Nov 14, 2006 2:52 pm
by Konne
MSDN Quote:
Remarks

A thread should not use IsWindow for a window that it did not create because the window could be destroyed after this function was called. Further, because window handles are recycled the handle could even point to a different window.

Posted: Tue Nov 14, 2006 3:00 pm
by Trond
Konne wrote:But that's the same with IsWindow/Gadget/Image etc.
Not really. Let's say you have a function that accepts an image. If you check the value with IsImage() you can be sure you've got a valid image.

Now let's say you write a function that accepts a pointer to MyStruct (80 bytes). You check the pointer with IsMemory() and feel safe, but you actually received a pointer to a NotMyStruct (4 bytes) and kaboom.

Posted: Tue Nov 14, 2006 4:49 pm
by Konne
But both things will lead to an error.