Shield wrote:1) If you allocate the memory (e. g. in a library you wrote), then you also provide a way to free it.
2) Generally, I prefer it the other way around where the user takes the responsibility and passes a block of memory to your function.
Hello Shield,
1) is the way I am going now. I also offer my own FreeMemory function in my object and store and track the memory address internally to check if the memory has already been released via my function.
2) I can't do it like that, because the user doesn't know how big the memory has to be. This is only decided within the function that allocates the memory. The function may have to perform a ReAllocate() several times. This depends on the data it have to process.
Josh wrote:The safest way is to have only one memory pointer and set it to 0 when you release the memory.
Yes, thats the way I do it now internally in my object, but this does not prevent the user from ignoring my FreeMemory() function and try to release the memory on his own.
freak wrote:Memory addresses can be re-used for new allocations once they have been freed. So even if the proposed IsMemoryID() function says that the memory is valid, you still don't know whether you can free it because there is no way to find out if it still references the same thing you once allocated. You could be freeing something that is still in use and have a random crash later.
@Freak, okay, I understand the dilemma.
However, I wonder why Fred didn't implemented the handling like with other PureBasic objects (e. g. Gadget).
For example, if you use ButtonGadget (#GadgetNr, x, y, width, heigth, text$[, flags]) you can either assign a unique gadget number yourself or use #PB_Any. Then the command itself returns a unique gadget number.
With this number you can perform an IsGadget() query without any problems.
So why not
?
Assuming you are using Allocatememory (1,1024), the command could immediately return the memory address as a result (because you delivered the unique memory number by itself -> 1).
If you use Allocatememory (#PB_Any, 1024), the command would return the unique memory number and a command
would be needed to get the real memory address.
This would be close to the logical structure of the other PureBasic objects and therefore an
command would also be possible without any problems.
PS: I have thought about it several times and now I have to add the following information to my text above:
The problem with the ambiguous *MemoryID or MemoryNumber is only solved if AllocateMemeory() always returns a MemoryNumber by itself. With AllocateMemory(MemoryNumber, Size) only #PB_Any should be used as MemoryNumber (you could omit the first parameter, but the function must only return the MemoryNumber). PureBasic must then ensure that a new, previously not used MemoryNumber is always generated until the end of the program. The best way to do this is to always increase the memory numbers by one after every AllocateMemory() or FreeMemory() call until the exe quits.
Code: Select all
MyMem = Allocatememory(1024) ; returns the MemoryNumber 1 for example
Debug MyMem ; prints 1
Debug MemoryAddress(MyMem) ; returns for example $3674861, the real address of the memoryblock
Debug IsMemory(MyMem) ; will return #True
Freememeory(MyMem) ; frees the memory at address $3674861 (could return #True to show memory was successfully freed)
Debug IsMemory(MyMem) ; will return #False
MyMem = Allocatemomory(512) ; returns the MemoryNumber 2
MyMem2 = Allocatememory(1024) ; returns the MemoryNumber 3
MyNewMem2 = ReAllocatememory(MyMem2, 4096) ; still returns the MemoryNumber 3
Freememory(MyMem) ; could return #True to show memory was successfully freed
Debug IsMemory(MyMem) ; will return #False
Debug IsMemory(MyMem2) ; will return #True
Debug IsMemory(MyNewMem2) ; will return #True
Freememory(MyMem) ; could return #False to show memory number is not longer valid
Freememory(MyNewMem) ; frees the memory (could return #True to show memory was successfully freed