AutoXenon Posted October 26, 2022 Share Posted October 26, 2022 (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 October 26, 2022 by AutoXenon Link to comment Share on other sites More sharing options...
Nine Posted October 26, 2022 Share Posted October 26, 2022 It has been discussed previously. It seems that garbage collection is at the source your "issue". “They did not know it was impossible, so they did it” ― Mark Twain Spoiler Block all input without UAC Save/Retrieve Images to/from Text Monitor Management (VCP commands) Tool to search in text (au3) files Date Range Picker Virtual Desktop Manager Sudoku Game 2020 Overlapped Named Pipe IPC HotString 2.0 - Hot keys with string x64 Bitwise Operations Multi-keyboards HotKeySet Recursive Array Display Fast and simple WCD IPC Multiple Folders Selector Printer Manager GIF Animation (cached) Screen Scraping Multi-Threading Made Easy Link to comment Share on other sites More sharing options...
pixelsearch Posted October 26, 2022 Share Posted October 26, 2022 Maybe this link could bring some light. Watch out, Valik answered there Link to comment Share on other sites More sharing options...
RTFC Posted October 27, 2022 Share Posted October 27, 2022 (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 October 28, 2022 by RTFC clarification pixelsearch 1 My Contributions and Wrappers Spoiler BitMaskSudokuSolver BuildPartitionTable CodeCrypter CodeScanner DigitalDisplay Eigen4AutoIt FAT Suite HighMem MetaCodeFileLibrary OSgrid Pool RdRand SecondDesktop SimulatedAnnealing Xbase I/O Link to comment Share on other sites More sharing options...
Recommended Posts
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 accountSign in
Already have an account? Sign in here.
Sign In Now