alogrep 0 Posted Monday at 11:03 PM HI. I have some stringgrids that use objects. For most of them the object is simply an integer (MySg.objects[c,r]:=Tobject(mynumber);; A few use complext object that I declare and assign a Create/destroy consctructor/desctuctor. Now when i try to delete an object of the "comples type" all works fine: the destructor takes care of it.. If i do if assigned(MySg.objects[c,r]) then MySg.objects[c,r].free On the Integer type, I get an AV exception. Perhaps the integer type object does not need to be freed. But then how do I inpect if the object is of integer type or not? MySG.objects[c,r].classname gives me a "not acessible" message. Any helop, please? Share this post Link to post
Dave Novo 56 Posted Monday at 11:18 PM What you are doing is very error prone, for the reasons you describe. If you are using low valued integers, you could inspect the value of the objects[x,y] and if the value is below some threshold, then do not free it. One way of doing this is 1. Make sure to set all objects[x,y] to zero 2. if setting it to an integer value, set it to the negative of the integer you want. Make sure to when using the value to negate it again 3. If setting to an object, store the pointer as a positive integer then, when freeing, only free where objects[x,y] is a positive value. I think that will work for 32 and 64 bit until you have set your 32 bit app to specifically use memory above 2GB block. Share this post Link to post
Remy Lebeau 1588 Posted yesterday at 04:25 AM 5 hours ago, alogrep said: Perhaps the integer type object does not need to be freed. Correct. 5 hours ago, alogrep said: But then how do I inpect if the object is of integer type or not? You can't. So, either store all objects only, or all integers only. Don't mix types. But, if you must, then you'll need to either wrap the integers inside of objects, or add an extra header in front of each value to identify its type, etc. 2 Share this post Link to post
Roger Cigol 132 Posted yesterday at 09:17 AM This strikes me as being a classic use case for inheritence. Define a base class of a type ObjectToStoreInStringGrid and then derive each of the types you need to store from this base class. Share this post Link to post
Remy Lebeau 1588 Posted 21 hours ago (edited) On 5/12/2025 at 4:18 PM, Dave Novo said: If you are using low valued integers, you could inspect the value of the objects[x,y] and if the value is below some threshold, then do not free it. Another option might be to use tagged pointers. Normally, objects are aligned in memory in such a way that certain bits in object pointers are always zero, so those bits can be repurposed if you are careful. For instance, if you limit your integer values to 31 bits (x86) or 63 bits (x64), you can use an unused bit in an object pointer to flag whether the pointer holds an integer value vs an object address, and just mask off the bit when extracting the value. For example: // this assumes objects are never stored at an odd-numbered memory address.. var intValue: Integer := ...; Objects[c,r] := TObject((NativeUInt(intValue) shl 1) or $1); ... var objValue: TObject := ...; Objects[c,r] := objValue; ... if (NativeUInt(Objects[c,r]) and $1) <> 0 then begin // is an integer... var intValue := Integer(NativeUInt(Objects[c,r]) shr 1); ... end else begin // is an object... var objValue := Objects[c,r]; ... end; ... if (NativeUInt(Objects[c,r]) and $1) = 0 then Objects[c,r].Free; Edited 11 hours ago by Remy Lebeau 1 Share this post Link to post
alogrep 0 Posted 12 hours ago Thank you all. I came up with another solution, wich seems to work The objects are either integer (very low, from 1-8)) or a typed (defined) object. So I do this: s:=''; try s:=objects[c,r].classname; // only the integer objects do not have a classname except end; if s<> '' then objects[c,r].free Anybody sees some unseen problem with this? Share this post Link to post
Remy Lebeau 1588 Posted 12 hours ago (edited) That is a very dangerous approach. Don't do it that way. First, there is no guarantee that accessing the ClassName on an invalid object will raise an exception. And second, reading from invalid memory may cause other side effects (ie, page faults, etc). Since your integers are very small, then you could simply look for integers first, and treat higher values as objects since they should never reside at such low memory addresses, eg: const MaxObjIntValue = 8; ... var value := NativeInt(Objects[c,r]); if (value >= 0) and (value <= MaxObjIntValue) then begin // is an integer, use value as needed... end else begin // is an object, use TObject(value) as needed... end ... if NativeInt(Objects[c,r]) > MaxObjIntValue then Objects[c,r].Free; Edited 11 hours ago by Remy Lebeau 1 Share this post Link to post
Kas Ob. 138 Posted 4 hours ago 8 hours ago, alogrep said: s:=''; try s:=objects[c,r].classname; // only the integer objects do not have a classname except end; if s<> '' then objects[c,r].free Anybody sees some unseen problem with this? I see undefined behaviour, this can go beyond degraded performance and go into literally corrupting the memory or the the worse the stack, triggering very hard to diagnose behavior, see.. calling ".classname" might land on an arbitrary method, and who knows what have been changed in that method/procedure/function... , literally nightmare stuff, and reproducing it is near impossible ! And of course the exception doesn't have to be silent, it could be triggered but after altering memory/stack, disguise the expected behavior and hide what have being changed somewhere. 1 Share this post Link to post