VarSetCapacity vs AHK_L

Ask for help, how to use AHK_H, etc.
pneumatic
Posts: 338
Joined: 05 Dec 2016, 01:51

VarSetCapacity vs AHK_L

29 Nov 2019, 01:50

HotKeyIt , https://www.autohotkey.com/boards/viewtopic.php?f=65&t=28803 wrote: The difference to main AutoHotkey is that #NoEnv is set by default and VarSetCapacity keeps memory in variable when capacity is changed.

I'm porting my script from _L to _H and going through all my VarSetCapacitys to ensure they are compatible with the above rule.

Which way is better:

Code: Select all

VarSetCapacity(var, %RuntimeBoundNumber% , 0)   ;0 = the var's binary bits are all set to 0 - how is this different to "blank"?
or

Code: Select all

var := ""  ;is blank better than setting all its bits to 0?
VarSetCapacity(var, %RuntimeBoundNumber%)
It seems the first way would be vulnerable to containing leftover memory if the capacity was decreased, since not all of its original bits would be filled to 0? Or are those leftover bits no longer associated with the var?

I'm unable to test it, as changing the capacity always results in a buffer size of 1 and junk contents:

Code: Select all

s := "TheQuickBrownFoxJumpedOverTheLazyDog"
VarSetCapacity(s, 1000000)

debug .= "s:`t" . s . "`n"
debug .= "size:`t" . StrPut(s , "UTF-16") ; returns number of chars written - the required buffer size 

msgbox % debug
exitapp
Image
guest3456
Posts: 3454
Joined: 09 Oct 2013, 10:31

Re: VarSetCapacity vs AHK_L

09 Dec 2019, 01:21

pneumatic wrote:
29 Nov 2019, 01:50
I'm unable to test it, as changing the capacity always results in a buffer size of 1 and junk contents:

Code: Select all

s := "TheQuickBrownFoxJumpedOverTheLazyDog"
VarSetCapacity(s, 1000000)

debug .= "s:`t" . s . "`n"
debug .= "size:`t" . StrPut(s , "UTF-16") ; returns number of chars written - the required buffer size 

msgbox % debug
exitapp
https://i.imgur.com/aqZ1R0W.png
on AHK_Lw, i get empty string, size 1
on AHK_Ha, i get "T+junk", size 1
on AHK_Hw, i get "T", size 1

i'm guessing you are running your test script on ansi (a) and not unicode (w)

look at this script:

Code: Select all

StrPutVar("TheQuickBrownFoxJumpedOverTheLazyDog", s, "UTF-16") 
MsgBox, % StrGet(&s, "UTF-16")
VarSetCapacity(s, 1000000)
MsgBox, % StrGet(&s, "UTF-16")
exitapp


StrPutVar(string, ByRef var, encoding)
{
    ; Ensure capacity.
    VarSetCapacity( var, StrPut(string, encoding)
        ; StrPut returns char count, but VarSetCapacity needs bytes.
        * ((encoding="utf-16"||encoding="cp1200") ? 2 : 1) )
    ; Copy or convert the string.
    return StrPut(string, &var, encoding)
}
the string turns blank on both AHK_La and AHK_Lw
but on both AHK_H's, it retains the string contents



VarSetCapacity source
AHK_L:
https://github.com/Lexikos/AutoHotkey_L/blob/36600809a348bd3a09d59e335d2897ed16f11ac7/source/script2.cpp#L16092
AHK_H:
https://github.com/HotKeyIt/ahkdll/blob/973709968f5698c1f95f95d28e94e897be1780ec/source/script2.cpp#L17860
diff:
https://quickdiff.net/?unique_id=B94CA363-3688-6151-0667-DF78BDEBC1B1

pneumatic
Posts: 338
Joined: 05 Dec 2016, 01:51

Re: VarSetCapacity vs AHK_L

11 Dec 2019, 02:17

guest3456 wrote:
09 Dec 2019, 01:21
i'm guessing you are running your test script on ansi (a) and not unicode (w)

I use Unicode 64-bit exclusively.

Speculation: the contents of the string are unpredictable and depend on what happens to be in that memory address on your particular system. On your system it happens to be something that gets decoded to empty or null characters.

eg. on my system if I put SetWorkingDir %A_ScriptDir% at the top, then instead of gibberish it becomes a string containing the truncated script directory.


guest3456 wrote:
09 Dec 2019, 01:21
look at this script:
the string turns blank on both AHK_La and AHK_Lw
but on both AHK_H's, it retains the string contents

It's because in my example I'm concatenating it which forces ahk to cast to string which for some reason converts it to gibberish

Code: Select all

s := "TheQuickBrownFoxJumpedOverTheLazyDog"
VarSetCapacity( s, 100000 )
MsgBox, % s
Image

Code: Select all

MsgBox, % "s: " . s
Image
HotKeyIt
Posts: 2364
Joined: 29 Sep 2013, 18:35
Contact:

Re: VarSetCapacity vs AHK_L

11 Dec 2019, 14:20

You will need to use VarSetCapacity(s, -1) to update the variable's internally-stored string length to the length of its current contents, see VarSetCapacity.
pneumatic
Posts: 338
Joined: 05 Dec 2016, 01:51

Re: VarSetCapacity vs AHK_L

12 Dec 2019, 00:20

HotKeyIt wrote:
11 Dec 2019, 14:20
You will need to use VarSetCapacity(s, -1) to update the variable's internally-stored string length to the length of its current contents, see VarSetCapacity.

Thanks, it works! And it was there in the documentation all along :oops: :oops: :oops: :oops: :oops:

But I'm still not sure if VarSetCapacity(var , %RuntimeBoundNumber% , 0) would guarantee the same result at runtime as manually doing var := "" before each and every VarSetCapacity.

I'm hoping it is the same, so I don't have to put all these extra If script is ahk_h, then var := "". It would be more elegant and efficient to just set the fillbyte to 0, to make it compatible with both _L and _H.

edit: to clarify, %RunTimeBoundNumber% could be any number, and could change to a different number at any time at runtime. So I need to be sure its contents are cleared and set to the new capacity, exactly as they are in _L.
pneumatic
Posts: 338
Joined: 05 Dec 2016, 01:51

Re: VarSetCapacity vs AHK_L

27 Dec 2019, 20:47

Since I couldn't get a clear answer on whether

Code: Select all

var := "" , VarSetCapacity(var, %RunTimeBoundNumber%)
Is equivalent to

Code: Select all

VarSetCapacity(var, %RunTimeBoundNumber%, 0)
The solution I ended up going with is to put comments in my _L script like this

Code: Select all

;#AHK_H var := ""
VarSetCapacity(var, 1024)
Then patch the script such that if InString(";#AHK_H") then replace that whole line with the bit after it (var := "").

It's a lot easier than trying to parse every instance of VarSetCapacity because they could be used as part of an if/else statement or continuation section that would need a lot of convoluted rules to ensure var:="" is being added in the correct place.

There is still an exception to the rule: multi line strings cannot have ;#AHK_H as they will be interpreted literally.

There might even be other exceptions I haven't thought of.
guest3456
Posts: 3454
Joined: 09 Oct 2013, 10:31

Re: VarSetCapacity vs AHK_L

29 Dec 2019, 13:41

why do you think that AHK_H requires you to set the variable to blank first, but AHK_L doesn't? is it because you DONT WANT the variable contents to be kept in memory when the size changes?

pneumatic
Posts: 338
Joined: 05 Dec 2016, 01:51

Re: VarSetCapacity vs AHK_L

05 Jan 2020, 03:27

guest3456 wrote:
29 Dec 2019, 13:41
why do you think that AHK_H requires you to set the variable to blank first, but AHK_L doesn't?
HotKeyIt , https://www.autohotkey.com/boards/viewtopic.php?f=65&t=28803 wrote: The difference to main AutoHotkey is that #NoEnv is set by default and VarSetCapacity keeps memory in variable when capacity is changed.
There are scenarios where not blanking a var first could result in different behaviour.

eg. if you wrote the _L script to evaluate the var to false if it failed to be set to anything.

Or a var might hold a specially formatted array used by a dll call, and could contain left over junk data from the last time you refreshed the array if its size is not the same each time you write to it, if its size is bound at runtime, such as an array of handles which changes depending on the system state.
HotKeyIt
Posts: 2364
Joined: 29 Sep 2013, 18:35
Contact:

Re: VarSetCapacity vs AHK_L

05 Jan 2020, 07:35

If you need the Variable to be empty why not use always VarSetCapacity(var,1024,0)?
guest3456
Posts: 3454
Joined: 09 Oct 2013, 10:31

Re: VarSetCapacity vs AHK_L

05 Jan 2020, 13:19

HotKeyIt wrote:
05 Jan 2020, 07:35
If you need the Variable to be empty why not use always VarSetCapacity(var,1024,0)?
i think he was worried that, if previously the memory was 2048, then the first 1024 would be set to 0, and then another 1024 would be leftover and unchanged.

so he wasn't sure which was closer to AHK_L compatible:

Code: Select all

VarSetCapacity(var,1024,0)
or

Code: Select all

var := ""
VarSetCapacity(var,1024)

pneumatic
Posts: 338
Joined: 05 Dec 2016, 01:51

Re: VarSetCapacity vs AHK_L

06 Jan 2020, 06:29

And also I'm not sure whether blanking a var is exactly the same as just setting all its bits to 0. It could be that blanking a var somehow removes it from the process's memory space and it becomes a null pointer instead of a pointer to a var which contains x bytes made up of 0's. Even ahk treats them differently:
https://www.autohotkey.com/docs/Variables.htm#Operators wrote:any blank value (empty string) or non-numeric value involved in a math operation is not assumed to be zero. Instead, it is treated as an error, which causes that part of the expression to evaluate to an empty string. For example, if the variable X is blank, the expression X+1 yields a blank value rather than 1.
HotKeyIt
Posts: 2364
Joined: 29 Sep 2013, 18:35
Contact:

Re: VarSetCapacity vs AHK_L

06 Jan 2020, 13:27

VarSetCapacity(var,1024,0) is closer to AHK_L.

Code: Select all

var:=10
MsgBox % var
VarSetCapacity(var,100,0) ; converts the variable to type string.
MsgBox % var

Return to “Ask for Help”

Who is online

Users browsing this forum: No registered users and 12 guests