Jump to content

DllStructs created in one scope gets dropped if chained with a function that returns a re-structured-by-pointer version of it


Recommended Posts

Posted (edited)
GUICreate('')
Local $unreliable_data, $reliable_data, $intermediate_ref, $labelunreliable = GUICtrlCreateLabel('',0,0,400,25), $labelreliable = GUICtrlCreateLabel('',0,30,400,25)
GUISetState()
HotKeySet('{esc}',quit)
While True
      $unreliable_data = parseStruct(createStruct())  ; struct technically goes out of scope, this saves a "slave struct" but the master struct gets dropped when it goes out of parseStruct's scope
      $intermediate_ref = createStruct()              ; struct scope gets transferred, this is a "master struct"
      $reliable_data = parseStruct($intermediate_ref) ; a "slave struct" of a master struct that is scoped here
      Sleep(100)                                      ; wait some time for garbage to get written into the freed memory 
      GUICtrlSetData($labelunreliable,DllStructGetData($unreliable_data,'msg'))
      GUICtrlSetData($labelreliable,DllStructGetData($reliable_data,'msg'))
WEnd


Func createStruct()
     Local $struct = DllStructCreate('char[16]')
     DllStructSetData($struct,1,'hello world')
     Return $struct
EndFunc

Func parseStruct($struct)
     Return DllStructCreate('char msg[16]',DllStructGetPtr($struct))
EndFunc

Func quit()
     Exit
EndFunc

 

 

There is no question that this is unergonomic/unexpected behaviour, but fixing it would involve having _every_ create-by-pointer DllStructs to be counted as valid references, which seems like it would be cause a massive headache, since modifying a struct by creating throwaway "lens structs" at different pointer locations is a common technique and would result in a struct never getting freed if a scripter is not careful with freeing every throwaway references. I don't know enough about the tradeoffs of AutoIt's internals of whether it is worth fixing or not, but at the very least there should be warnings about this kind of memory safety pitfalls in the DllStruct documentations.

Edited by AutoXenon
  • AutoXenon changed the title to DllStructs created in one scope gets dropped if chained with a function that returns a re-structured-by-pointer version of it
Posted (edited)
Local $unreliable_data = DllStructCreate('char[16]') ; create container within the scope where it's used!
DllStructSetData($unreliable_data,1,DllStructGetData(parseStruct(createStruct()),1)) ; get contents immediately
Sleep(1000)
ConsoleWrite(DllStructGetData($unreliable_data,1) & @CRLF)  ; works

Func createStruct()
     Local $struct = DllStructCreate('char[16]')
     DllStructSetData($struct,1,'hello world')
     Return $struct
EndFunc

Func parseStruct($struct)
     Return DllStructCreate('char msg[16]',DllStructGetPtr($struct))
EndFunc

Simple rule: Create containers within the scope where they are used (and not in subsidiary scopes). Even if the language allows you to break this rule, you should expect trouble if you do. And if you must fill/edit a (multi-element) struct in a lower-level function, then parse it ByRef (so no needless copies are made) :

Local $reliable_data = DllStructCreate('char[16];int;float')
parseStruct($reliable_data) ; using ByRef

ConsoleWrite(DllStructGetData($reliable_data,1) & @CRLF)
ConsoleWrite(DllStructGetData($reliable_data,2) & @CRLF)
ConsoleWrite(DllStructGetData($reliable_data,3) & @CRLF)

Func fillStruct(ByRef $struct)
     DllStructSetData($struct,1,'hello world')
     DllStructSetData($struct,2,123)
     DllStructSetData($struct,3,0.456)  ; not exactly representable as a float, but you get the idea
EndFunc

Func parseStruct(ByRef $struct) ; completely pointless intermediary func, just for illustration
     fillStruct($struct)
EndFunc

 

Edited by RTFC
clarification

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...