Opened 11 years ago
Closed 5 years ago
#2955 closed Bug (Fixed)
Using Is### breaks Maps passed ByRef
| Reported by: | anonymous | Owned by: | Jon |
|---|---|---|---|
| Milestone: | 3.3.15.3 | Component: | AutoIt |
| Version: | 3.3.13.19 | Severity: | None |
| Keywords: | Cc: |
Description
Depending on various things, some map values can be broken
Shortest working example i got:
#AutoIt3Wrapper_Version=Beta
#include <Debug.au3>
WTF() ; works, if outside of func
MsgBox(0, Default, "Yep!")
Func WTF()
Local $MAP[]
$MAP["mod"] = "Mod"
$MAP["more"] = "More actions"
$MAP["delete"] = "Delete"
Local $sTest1 = $MAP["more"] ; after this $Map["more"] is Null
Local $sTest2 = $MAP["more"]
_Assert("$sTest1 == $sTest2") ; Assertion Failed
EndFunc
Attachments (0)
Change History (9)
comment:1 Changed 11 years ago by Melba23
comment:2 Changed 11 years ago by Melba23
- Resolution set to No Bug
- Status changed from new to closed
comment:3 Changed 11 years ago by anonymous
Um... Sorry... There is no problem with _Assert() at all. I trying to make a shorter example and lost problem in process.
Seems that this problem is related to some non-trivial code when passing maps or sub-maps to user function without and using Is<KindOf> functions AND only if you use some specific keys.
Here is a valid example (no assertion is used here):
#AutoIt3Wrapper_Version=Beta
AutoItSetOption("MustDeclareVars", 1)
Global $TEST = "more" ; works correctly if you use other sting
Global $mMap = Map()
Error($mMap)
Func Error($mTest) ; works correctly if you use ByRef
Local $sTest1 = $mTest[$TEST]
IsString($mTest["mod"]) ; works correctly if you comment this line
Local $sTest2 = $mTest[$TEST]
MsgBox(0, Default, VarGetType($sTest1) & ":" & $sTest1 & @CRLF & VarGetType($sTest2) & ":" & $sTest2)
EndFunc
Func Map()
Local $mTest[]
$mTest["mod"] = "Mod"
$mTest["caption"] = "Mod list (%s)"
$mTest["no_game_dir1"] = "no game dir - select from ""More actions"""
$mTest["up"] = "Move up"
$mTest["down"] = "Move down"
$mTest["enable"] = "Enable"
$mTest["disable"] = "Disable"
$mTest["missing"] = "%s (missing mod)"
$mTest["remove"] = "Remove"
$mTest[$TEST] = "More actions"
; works correctly if you comment remaining items
$mTest["plugins"] = "Plugins"
$mTest["homepage"] = "Go to webpage"
$mTest["delete"] = "Delete"
$mTest["delete_confirm"] = "Do you really want to delete this mod? \n%s\n\n(The mod will be moved to recycle bin, if it's possible))"
$mTest["add_new"] = "Add new mod(s)"
$mTest["compatibility"] = "Compatibility"
$mTest["open_dir"] = "Open mod directory"
Return $mTest
EndFunc
comment:4 Changed 11 years ago by Melba23
- Resolution No Bug deleted
- Status changed from closed to reopened
- Summary changed from Map content is randomly broken to Using Is### breaks Maps passed ByRef
I now agree that there is a problem - but not the one you think you have found. I believe it happens when you pass a Map ByRef and check on the values. This example shows it clearly:
#AutoIt3Wrapper_Version=Beta
AutoItSetOption("MustDeclareVars", 1)
Global $TEST = "more"
Global $mMap = Map()
For $vKey In MapKeys($mMap)
ConsoleWrite($vKey & ": " & @TAB & $mMap[$vKey] & @CRLF)
Next
ConsoleWrite(@CRLF)
_Error_ByRef($mMap)
ConsoleWrite(@CRLF)
_Error_Global()
Func _Error_ByRef($mTest)
ConsoleWrite(@CRLF & "ByRef - before IsString" & @CRLF)
For $vKey In MapKeys($mTest)
ConsoleWrite($vKey & ": " & @TAB & $mTest[$vKey] & @CRLF)
Next
Local $sTest1 = $mTest[$TEST]
IsString($mTest["mod"]) ; This is the problem line <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
ConsoleWrite(@CRLF & "ByRef - after IsString" & @CRLF)
For $vKey In MapKeys($mTest)
ConsoleWrite($vKey & ": " & @TAB & $mTest[$vKey] & @CRLF)
Next
Local $sTest2 = $mTest[$TEST]
MsgBox(0, "ByRef", VarGetType($sTest1) & ": " & $sTest1 & @CRLF & VarGetType($sTest2) & ": " & $sTest2)
EndFunc
Func _Error_Global()
ConsoleWrite(@CRLF & "Direct - before IsString" & @CRLF)
For $vKey In MapKeys($mMap)
ConsoleWrite($vKey & ": " & @TAB & $mMap[$vKey] & @CRLF)
Next
Local $sTest1 = $mMap[$TEST]
IsString($mMap["mod"])
ConsoleWrite(@CRLF & "Direct - after IsString" & @CRLF)
For $vKey In MapKeys($mMap)
ConsoleWrite($vKey & ": " & @TAB & $mMap[$vKey] & @CRLF)
Next
Local $sTest2 = $mMap[$TEST]
MsgBox(0, "Global", VarGetType($sTest1) & ": " & $sTest1 & @CRLF & VarGetType($sTest2) & ": " & $sTest2)
EndFunc
Func Map()
Local $mTest[]
$mTest["mod"] = "Mod"
$mTest["caption"] = "Mod list (%s)"
$mTest["no_game_dir1"] = "no game dir - select from ""More actions"""
$mTest["up"] = "Move up"
$mTest["down"] = "Move down"
$mTest["enable"] = "Enable"
$mTest["disable"] = "Disable"
$mTest["missing"] = "%s (missing mod)"
$mTest["remove"] = "Remove"
$mTest[$TEST] = "More actions"
; works correctly if you comment remaining items
$mTest["plugins"] = "Plugins"
$mTest["homepage"] = "Go to webpage"
$mTest["delete"] = "Delete"
$mTest["delete_confirm"] = "Do you really want to delete this mod? \n%s\n\n(The mod will be moved to recycle bin, if it's possible))"
$mTest["add_new"] = "Add new mod(s)"
$mTest["compatibility"] = "Compatibility"
$mTest["open_dir"] = "Open mod directory"
Return $mTest
EndFunc
So the bug appears to be using Is##### on a Map passed ByRef - I have amended the title.
M23
P.S. By the way, I notice the reference to "game" in your script - could I gently point you to the Forum rules:
http://www.autoitscript.com/forum/index.php?app=forums&module=extras§ion=boardrules
comment:5 Changed 11 years ago by anonymous
... but not the one you think you have found...
I don't know what sort of problem it is. There is so many things should be used together to reproduce this bug (so i can make some small changes to code and it will work correctly)... but in any way Is<KindOf> should not modify its param.
... reference to "game" ...
This script don't interact with game (only can launch process) or game server in any way.
See gen_lng_validate.au3, lng_auto.au3 (this "bug" affects only "more" key) and lng\english.json for details
https://bitbucket.org/SyDr/ramm/src/0d6f035cf547b66d425f91a72dda41a189e8f25d?at=no_regrets
comment:6 Changed 11 years ago by jchd18
M23,
$mTest is not passed ByRef in the code exposed.
If one changes the function into:
Func _Error_ByRef(ByRef $mTest)
then everything works as expected.
But with your code, this:
Local $sTest1 = $mTest[$TEST]
assigns Null to $sTest1.
comment:7 Changed 11 years ago by Melba23
jchd,
I realised that last night as I went to bed - the problem happens when the Map is passed as a parameter and a copy is made. Sorry for the confusion.
I will try and get a simple reproducer script working today and post it in "Dev Chat" - this needs more scrutiny that it is getting in Trac.
M23
comment:8 Changed 10 years ago by anonymous
Hi. Any news?
comment:9 Changed 5 years ago by Jon
- Milestone set to 3.3.15.3
- Owner set to Jon
- Resolution set to Fixed
- Status changed from reopened to closed
Fixed by revision [12297] in version: 3.3.15.3
Guidelines for posting comments:
- You cannot re-open a ticket but you may still leave a comment if you have additional information to add.
- In-depth discussions should take place on the forum.
For more information see the full version of the ticket guidelines here.

Nothing wrong with the Map itself - the problem is in way the statement is passed to the _Assert function. I am investigating further.
M23
Edit: The problem arises because the 2 variables in the passed statement are Local to the WTF function and so are not recognised by the _Assert function. So the passed string is executed as a literal string and fails. You can see this happening in this example script:
#include <MsgBoxConstants.au3> Global $sTest1, $sTest2 ; Comment out to see the fail <<<<<<<<<<<<<<<<<<<<<<<<<<<<< WTF() ; works, if outside of func MsgBox(0, Default, "Yep!") Func WTF() Local $MAP[] $MAP["mod"] = "Mod" $MAP["more"] = "More actions" $MAP["delete"] = "Delete" For $vKey In MapKeys($MAP) ConsoleWrite($vKey & " - " & $Map[$vKey] & @CRLF) Next $sTest1 = $MAP["more"] For $vKey In MapKeys($MAP) ConsoleWrite($vKey & " - " & $Map[$vKey] & @CRLF) Next ConsoleWrite("$sTest1: " & $sTest1 & @CRLF) $sTest2 = $MAP["more"] For $vKey In MapKeys($MAP) ConsoleWrite($vKey & " - " & $Map[$vKey] & @CRLF) Next ConsoleWrite("$sTest2: " & $sTest2 & @CRLF) ConsoleWrite(@CRLF) _Assert_Mod("$sTest1 == $sTest2") EndFunc Func _Assert_Mod($sCondition, $bExit = True, $nCode = 0x7FFFFFFF, $sLine = @ScriptLineNumber, Const $iCurERR = @error, Const $iCurEXT = @extended) Local $bCondition = Execute($sCondition) ConsoleWrite($sCondition & " : " & $bCondition & " - " & Execute($sCondition) & @CRLF) If Not $bCondition Then MsgBox($MB_SYSTEMMODAL, "AutoIt Assert", "Assertion Failed (Line " & $sLine & "): " & @CRLF & @CRLF & $sCondition) If $bExit Then Exit $nCode EndIf Return SetError($iCurERR, $iCurEXT, $bCondition) EndFunc ;==>_AssertAs you can see the Map contents are unchanged, but when the passed variables are not Global in scope the _Assert function fails.
The basic problem is that Execute needs to recognise the variable names in the passed string as variables - and it seems that it only looks in the Global variable list. So a possible bug, but nothing to do with Maps per se I suggest that you open a new ticket that covers the failure of _Assert when passed Local variables.
M23