Why is Object Ptr an illigal pointer type?

BlitzMax Forums/BlitzMax Programming/Why is Object Ptr an illigal pointer type?

Fabian.(Posted 2006) [#1]
Hi!

I noticed that "Object Ptr" isn't a correct BlitzMax variable data type.
But why?
It could be simply defined as a pointer to a variable of type "Object". That means a pointer to a pointer to a BBObject struct or (in C) "typedef BBObject** bbObjectPtrType". (BBObject defined in "mod/brl.mod/blitz.mod/blitz_object.h")

I thought this data type was allowed in any version before; but why isn't it allowed still?
Because the GC behaviour has changed?
I think if everyone is using this type carefully there will be no problems when using "Object Ptr" data type with the GC.

Here's an example which would run correctly with the GC if "Object Ptr" data type would be allowed:
Strict
Framework brl.blitz

Local O:Object = New T'creates a new object, blitzmax GC cares about the object referenced by O
Local P:Object Ptr = Varptr O'get the address of the variable in memory, the GC doesn't care about variables of type "? Ptr"
DoAnything P'call a function; while this function is executed the variable O is still in scope and the object has at least 1 reference
'now the function has ended; but the object's reference counter still counts 1 reference: the main programme's variable O
'Go on with the main programme;the object can still be accessed by O and P[0]
P = Null
'now the object can only be accessed by O; but the reference counter stays at the prev. value (1 reference: O)
O = Null'this causes the objects reference counter to decrement: so there's no reference and the object will be deleted soon
'Go on with the code

Function DoAnything ( P:Object Ptr )
  Local O:Object = P [ 0 ]'set a new variable O to this object; now it has 2 references: the main programme's O and the sub programme's O
  'Do anything with the object; all the time this code runs the object has at least these 2 references
EndFunction'now the function ends; this causes the sub programme's variable O to run out of scope, so the object's reference counter decrements

Type T
EndType


So please, if anyone knows, tell me why is this type not allowed in this version; and: will it be re-allowed in any future version?


Yan(Posted 2006) [#2]
I'm starting to think that I'm the only person that ever reads the release notes... ;o)
1.18 Release
************
...
The compiler no longer allows you to create a pointer to an object via VarPtr (this was always supposed to be the case, but somehow it got overlooked!). Therefore, 'Object Ptr' (or ' Ptr' etc) is no longer accepted. This is because there is not any safe way to write to such a pointer without massively confusing garbage collection/detection. It is still legal to convert an object reference to a 'Byte Ptr', but you should be aware the pointer will only be valid while the object remains 'in scope'.
...



Fabian.(Posted 2006) [#3]
I don't really think that "Object Ptr" is a risk for the GC if the user keeps track of the object references as posted before. I don't think defining these things as not allowed will help to prevent GC confusing. If anyone wants to confuse the GC this person will always find a way to do so. For example getting a objects variable address can be done like this:
varptr.bmx:
Strict
Framework brl.blitz

Import brl.standardio

Import "varptr.s"

Local I'this variable is just to show that the returned value is right
Local O:Object = New T
Print Int Varptr I'this variable is just 4 bytes above on the stack
Print Int _Varptr ( O )'you can see a difference of 4 bytes

Type T
EndType

Extern
  Function _Varptr:Byte Ptr ( O:Object Var )
EndExtern
varptr.s:
format MS COFF
public __Varptr
__Varptr:
mov eax,dword [esp+4]
ret

There's always such a dirty way to trick the BlitzMax compiling and GC rules.
But I don't want to use that way.
It would be better to re-allow the Object Ptr and then set an explicit warning into the docs that Varptr + an object's variable will not return a pointer to the object and that the person using this feature has to make sure that pointer's to object variable's are only accessed when the object variable stay's valid.

It isn't very difficult to implement the Object Ptr type and it wouldn't slow down the programme, it wouldn't decrease the functionality of existing features, but it would provide a full downwardly compatibility (to all applications: the ones before and after 1.18).
You see: there are only advantages, no disadvantages


Dreamora(Posted 2006) [#4]
the larger problem is: If you use such dirty tricks you will better not post bug errors as they can arise from this tricks (as they can from using a newer MingW than 3.1 and certainly do as well)

The reasons pointer were never meant to be in is quite easy btw and a reason that can and must not be broken:
Pointers are not type safe!
But BM is, which is why even if pointer stayed in, they would be useless, because you can't cast back from Pointer to any Type within a type safe environment as the "source type" of something you have a pointer is not defined and casting thus illegal.
If you only need the pointer to safe something you can still do that by somePtr:Byte Ptr = varptr someObj:Object
But as mentioned: not typesafe and backcasting won't work (directly at least. I know at least 1 workaround but won't post it as it breaks RefCount and GC quite easily if used by unexperienced user. But to give you a hint on how: memcpy is your friend if you use your target typeinstances varptr and the byte ptr as well as sizeof(type) ...)


btw: And your modules aren't compatible to before 1.16/ 1.18 anyway, no mather if Object Ptr is broken again or not, as the module format has changed with both and everything compiled after is broken anyway to those. Ask windows BM demo users as the Win Demo still is 1.12 instead of 1.20 as the OSX demo


Fabian.(Posted 2006) [#5]
Thanks a lot; for now I found the workaround with memopy; it works wonderful, thanks.
But okey I see, it's better when managing this directly by object references if possible. This is the best solution for most problems, because it surely doesn't confuse the GC (even if there're some more ways to do so).
However Object Ptr would be still a nice addition to BMX to solve some problems the other ways don't work.