Compiler directive to ignore unusually high IDs

Just starting out? Need help? Post your questions and find answers here.
Mistrel
Addict
Addict
Posts: 3415
Joined: Sat Jun 30, 2007 8:04 pm

Compiler directive to ignore unusually high IDs

Post by Mistrel »

I like to use unique IDs as often as possible and make heavy use of #PB_Any. The problem I'm encountering is when I want to reuse these IDs PureBasic has a fit when the debugger is on. I get messages like:
[ERROR] #Image object number is very high (over 100000), are You sure of that ?
I don't care what the number actually is, since it's always provided for me. But it does seem as if PureBasic does care. And this is making it harder to code.

So, I'm doing a linear search every time I want a free ID. This is slow and heavily degrades the performance of these functions. I don't care for that but I don't see any other option.
PB
PureBasic Expert
PureBasic Expert
Posts: 7581
Joined: Fri Apr 25, 2003 5:24 pm

Re: Compiler directive to ignore unusually high IDs

Post by PB »

You're using it wrong if you get that message. I bet you're using the result of
#PB_Any without ImageID() with it. Show me the code that gives this error
and it'll be as I say. :)
I compile using 5.31 (x86) on Win 7 Ultimate (64-bit).
"PureBasic won't be object oriented, period" - Fred.
Mistrel
Addict
Addict
Posts: 3415
Joined: Sat Jun 30, 2007 8:04 pm

Post by Mistrel »

Code: Select all

ImageID=CreateImage(#PB_Any,32,32)
CreateImage(ImageID,32,32) ;/ Attempting to reuse the same image ID
PB
PureBasic Expert
PureBasic Expert
Posts: 7581
Joined: Fri Apr 25, 2003 5:24 pm

Post by PB »

CreateImage is meant for low number ranges, like 0 to 1000 (maybe not
even that high). So the result of #PB_Any can't be used with it, like I said,
as that always returns a number outside of that range. Same for gadgets.
I compile using 5.31 (x86) on Win 7 Ultimate (64-bit).
"PureBasic won't be object oriented, period" - Fred.
Mistrel
Addict
Addict
Posts: 3415
Joined: Sat Jun 30, 2007 8:04 pm

Post by Mistrel »

Actually, it can. The error only occurs with the debugger on. And having #PB_Any provide an ID that isn't reusable is counter-intuitive to developing reusable code.
PB
PureBasic Expert
PureBasic Expert
Posts: 7581
Joined: Fri Apr 25, 2003 5:24 pm

Post by PB »

Okay, it can, but it's not meant to, as I said. Hence the error when you try.
You're trying to code it in such a way that PureBasic doesn't expect.
I compile using 5.31 (x86) on Win 7 Ultimate (64-bit).
"PureBasic won't be object oriented, period" - Fred.
Mistrel
Addict
Addict
Posts: 3415
Joined: Sat Jun 30, 2007 8:04 pm

Post by Mistrel »

PB wrote:You're trying to code it in such a way that PureBasic doesn't expect.
Hence why I'm requesting this compiler directive and my post is in the "Feature Requests and Wishlist" section and not "Bugs".
User avatar
Kaeru Gaman
Addict
Addict
Posts: 4826
Joined: Sun Mar 19, 2006 1:57 pm
Location: Germany

Post by Kaeru Gaman »

well this just IS the wrong way.

you should not care about "reusing" this ID, it is not the NUMBER.
when you pass it as argument, it would be interpreted as number and thus the whole gain of using PB_Any is for the fishes, there will be an incredible large numbertable created.
to avoid this, the debugger drops the warning.

if you want to reuse something, you should pass a newly created ID to the variable.
you can make sure not to leak by freeing the first ID in advance.

Code: Select all

ImageID = CreateImage(#PB_Any,32,32)
...
FreeImage( ImageID )
ImageID = CreateImage(#PB_Any,32,32) ; reuse the image 
PS

in fact, you ARE not at all reusing the same Image.

the ID return when using PB_Any is kind of a PB-internal Handle of the Image. (not the OS_Handle of the Object...)
The Number you can enter directly is the Index of the internal Table for PB-Handles.

that means, when you use Number 1000, PB will create a 1000 Fields big Table of Handles,
and put the Handle for this Image into the table on index 1000.

when you use PB_Any, there will be no Index and no place in the table,
the PB-handle will be used directly.
oh... and have a nice day.
Mistrel
Addict
Addict
Posts: 3415
Joined: Sat Jun 30, 2007 8:04 pm

Post by Mistrel »

If I need 10 images at some particular point in my program where each of those images may change dimensions I need to be able to pass it back to CreateImage to reinitialize the bitmap in memory.

If I'm referencing these image IDs elsewhere in my program I would have to keep track of each reference (which could also be variable) and then go around and update every instance.

This is a lot of additional and unnecessarily difficult work when all I want it to reuse the same ID that's already stored within PB.
Kaeru Gaman wrote:and thus the whole gain of using PB_Any is for the fishes ..
The whole point of using #PB_Any is to not have to perform a linear search every time I need a free ID. Otherwise I have to create my own lookup table of active and free IDs as well as sort these structures and also provide additional search functions to pull out the next free ID as quickly as possible.

The "point" of #PB_Any, correct me if I'm wrong, is to provide a convenient means of acquiring a free ID that will not collide with any active ID and without the additional need for supporting functions.

Now, I want to reuse this wonderfully provided ID just as I would be able to use any normal ID. The problem I have with the current implementation is that it does not allow the use of these #PB_Any IDs were it's perfectly legal to use a normal ID. That is my point. I'm fully capable of being responsible with my IDs and don't need the debugger to question whether I'm really sure that the ID it provided me is acceptable.

The question for Fred/freak here is: when reusing an existing #PB_Any ID does it resize the internal ID table or simply reuse the existing entry. If this is the case then I believe the warning would be more suited for numbers larger than 100,000 which do not already exist.
User avatar
Kaeru Gaman
Addict
Addict
Posts: 4826
Joined: Sun Mar 19, 2006 1:57 pm
Location: Germany

Post by Kaeru Gaman »

> If I'm referencing these image IDs elsewhere in my program I would have to keep track of each reference (which could also be variable) and then go around and update every instance.
yes, you'll have to.
thus, store the returned value in your own lookup table.

> This is a lot of additional and unnecessarily difficult work
when you change an image you always have to update the containers it is in, so where is it additional work?

this far I don't agree with you. but:

> when reusing an existing #PB_Any ID does it resize the internal ID table or simply reuse the existing entry.
this definitely is the cardinal question.

-------------
I think the whole deal with the warning is that PureBasic needs it's lookup-table, if the ID used is not the internal handle.

when a Beginner would use an ImageNumber of 47110815 just for fun,
and PB interpretes it as the internal handle, the program will crash.
thus there is the warning.

------------

additionally, one point just occuring to me...

is it even possible to reuse the internal handle, when altering the size of an image?
the bitmap memory has to be reallocated, so the pointer will change,
if the bitmap is a part of the object structure as I suspect, the whole object has to be reallocated.

I'm not completely sure but I think the "internal handle" is the pointer to the object structure....

then, reusing is just impossible.
oh... and have a nice day.
freak
PureBasic Team
PureBasic Team
Posts: 5929
Joined: Fri Apr 25, 2003 5:21 pm
Location: Germany

Post by freak »

Mistrel wrote:The question for Fred/freak here is: when reusing an existing #PB_Any ID does it resize the internal ID table or simply reuse the existing entry. If this is the case then I believe the warning would be more suited for numbers larger than 100,000 which do not already exist.
If you pass a #PB_Any created number (which is usually very high as it is a direct memory address) PB will try to allocate the object among the static numbers (which are allocated in an array), so you get a very large array as a result and tons of wasted memory. Thats why there is the debugger message.

PB Objects are managed in the following way at the moment:
  • If you pass in your own number, the object structures are kept in an array, indexed by this number (for this reason, passing a high number is bad)
  • If you use #PB_Any, the returned value is a direct memory address of an allocated object structure
It is slightly more complicated in thread mode, but that doesn't matter here. This way works fine because all OS actually reserve low memory locations for system use and do not return them as a result of a usermode memory allocation, so there are no collisions.

The reason why reusing a #PB_Any number is not possible is because it cannot be determined wether the number you passed in actually references a valid PB object without comparing the number to all existing objects (which is very slow of course). For the static numbers it is easy to verify as we only have to check if the number fits the bounds of the array and then look at the entry to see if it is valid.

Take these sequences:

Code: Select all

CreateImage(1, ...)
FreeImage(1)
CreateImage(1, ...)

a = CreateImage(#PB_Any, ...)
FreeImage(a)
CreateImage(a, ...)
The first sequence works perfectly well. You can even skip the FreeImage() as PB automatically frees an object if the number is reused. Not so for the second sequence though. After the 'FreeImage(a)' call, a is actually the address of now freed memory. If the next CreateImage(a, ...) tries to reuse it you get a crash, or worse you just corrupt some random part of your program's memory.

So you see, the two number systems cannot easily be treated in the exact same way (without a big speed hit for verifying objects). We could allow the reuse of 'a' as a number if the object was not freed inbetween, but then it is still not fully the same behavior and even more dangerous in terms of hard to find bugs in my opinion.

That said, the debugger could provide a more helpful message if you try to use a #PB_Any number like this. (because the debugger actually does the slow object verification). This should make things a bit more clear.

(Note: The internals of the object management are just that: internals. It can change anytime in the future. Don't rely on this.)
quidquid Latine dictum sit altum videtur
Post Reply