Jump to content



Photo

Problem with array assignment and ByRef functions


  • Please log in to reply
9 replies to this topic

#1 Nutster

Nutster

    Developer at Large

  • Developers
  • 1,450 posts

Posted 03 January 2008 - 05:55 AM

Using release 3.2.10.0, I have found a very disconcerting issue. I was creating a set of sorting functions in AutoIt when I noticed a strange behaviour of array assignment. When I assign a variable from an entire array and pass the variable to a UDF ByRef, I find that the original array is affected as well. Here is an example that one of the other users in Genaral Help simplified for me and it has the effect of modifying $avOne by playing with $avTwo. After the assignment, shouldn't these be separate arrays? The only work-around I have found so far is to assign to the element of $avTwo, which seems to break the link and actually have the arrays be copies.

#include <array.au3> Global $avOne[2] = [1, 2] Global $avTwo = $avOne ;~ $avTwo[0] = $avOne[0] ; breaks the link so the weird behaviour is not seen. _Swap($avTwo[0], $avTwo[1]) _ArrayDisplay($avOne, "Debug: $avOne") _ArrayDisplay($avTwo, "Debug: $avTwo") Func _Swap(ByRef $vA, ByRef $vB)     Local $T = $vA     $vA = $vB     $vB = $T EndFunc   ;==>Swap

David NuttallNuttall Computer ConsultingAutoIt allows me to re-invent the wheel so much faster.An Aquarius born during the Age of AquariusI'm off to write a wizard, a wonderful wizard of odd...





#2 JerryD

JerryD

    Polymath

  • Active Members
  • PipPipPipPip
  • 247 posts

Posted 03 January 2008 - 10:51 AM

Using release 3.2.10.0, I have found a very disconcerting issue. I was creating a set of sorting functions in AutoIt when I noticed a strange behaviour of array assignment. When I assign a variable from an entire array and pass the variable to a UDF ByRef, I find that the original array is affected as well. Here is an example that one of the other users in Genaral Help simplified for me and it has the effect of modifying $avOne by playing with $avTwo. After the assignment, shouldn't these be separate arrays? The only work-around I have found so far is to assign to the element of $avTwo, which seems to break the link and actually have the arrays be copies.

#include <array.au3> Global $avOne[2] = [1, 2] Global $avTwo = $avOne ;~ $avTwo[0] = $avOne[0] ; breaks the link so the weird behaviour is not seen. _Swap($avTwo[0], $avTwo[1]) _ArrayDisplay($avOne, "Debug: $avOne") _ArrayDisplay($avTwo, "Debug: $avTwo") Func _Swap(ByRef $vA, ByRef $vB)     Local $T = $vA     $vA = $vB     $vB = $T EndFunc   ;==>Swap

In the third line you're assiging $avTwo to point to the same memory address as $avOne, so they're both pointing to the same thing. When you swap $avTwo, only $avTwo is swapped, but both arrays are still pointing to the same thing so effectively they're both swapped. If you change the line to Global $avTwo[2] = [1,2] or Global $avTwo[2]
$avTwo[0] = $avOne[0]
$avTwo[1] = $avOne[1]
, only $avTwo is changed by the call to _Swap.

Edited by JerryD, 03 January 2008 - 10:53 AM.


#3 MadBoy

MadBoy

    Universalist

  • Active Members
  • PipPipPipPipPipPip
  • 829 posts

Posted 03 January 2008 - 01:10 PM

In the third line you're assiging $avTwo to point to the same memory address as $avOne, so they're both pointing to the same thing. When you swap $avTwo, only $avTwo is swapped, but both arrays are still pointing to the same thing so effectively they're both swapped. If you change the line to Global $avTwo[2] = [1,2] or Global $avTwo[2]
$avTwo[0] = $avOne[0]
$avTwo[1] = $avOne[1]
, only $avTwo is changed by the call to _Swap.

In my opinion the behaviour is not correct. You don't want $avOne to be swapped at all. So you "copy" the array to new array and only work with the new array. Don't think the old array should change at same time.

#4 Richard Robertson

Richard Robertson

    Universalist

  • Active Members
  • PipPipPipPipPipPip
  • 9,692 posts

Posted 03 January 2008 - 01:37 PM

Variants should never be a reference to another variable unless passed ByRef. I believe this is incorrect behavior.

#5 JerryD

JerryD

    Polymath

  • Active Members
  • PipPipPipPip
  • 247 posts

Posted 03 January 2008 - 02:36 PM

Variants should never be a reference to another variable unless passed ByRef. I believe this is incorrect behavior.

You're right, so don't do it! When you use ByRef in a function, what you're saying is "change the value of the variable contained in the memory address REFERENCED by the variable passed. In other languages (in C anyway) pointers are not handled as elegantly or easily as in AutoIt, but that's all ByRef means - use the value at the memory address POINTED TO by this variable - not the VALUE of the variable.

When you create the variable Global $avOne[2], you're saying that the variable $avOne is a MEMORY ADDRESS that points to two variables $avOne[0] and $avOne[1], each of which contain values.

When you declare $avTwo and assign it to the value of $avOne, the only value it can be assigned is the value of $avOne which is a memory address.

While I understand your confusion, but most languages would behave the same, and more importantly, once you know about it, you know how to use it properly.

#6 Valik

Valik

    Former developer.

  • Active Members
  • PipPipPipPipPipPip
  • 18,879 posts

Posted 03 January 2008 - 03:13 PM

Ummm Jerry, you might want to shut up now. You have no clue what you're on about. The line "Global $avTwo = $avOne" is a COPY. It is not the initialization of a pointer. AutoIt doesn't use pointers to Variants. You've just fabricated a whole story why this works which makes no sense in AutoIt.

This is a bug.

#7 JerryD

JerryD

    Polymath

  • Active Members
  • PipPipPipPip
  • 247 posts

Posted 03 January 2008 - 03:23 PM

Ummm Jerry, you might want to shut up now. You have no clue what you're on about. The line "Global $avTwo = $avOne" is a COPY. It is not the initialization of a pointer. AutoIt doesn't use pointers to Variants. You've just fabricated a whole story why this works which makes no sense in AutoIt.

This is a bug.

Hate to tell you Valik, but I actually DO have a clue, and have been working with programing and computers longer than you've been working on being a nasty snotty SOB.

I don't mind being wrong, but the fact is my explanation makes perfect sense and is not off base, especially for someone that has no knowledge of the inner workings of the language, hence the reason for my post.

So what's the reason for yours? Just enjoy being an ahole?

#8 -Ultima-

-Ultima-

    Universalist

  • Active Members
  • PipPipPipPipPip
  • 267 posts

Posted 03 January 2008 - 04:03 PM

Heh, randallc and I noticed this same problem here a while ago when I was messing with introsort. The only difference is that I didn't realize it was a bug -- I thought it was some copy-on-write optimization behavior xD

Good to hear that it's getting fixed; it was becoming a teeny bit annoying to test some functions because I kept having to remember to write to the array once before testing :)

Edited by -Ultima-, 03 January 2008 - 04:13 PM.

[ WinINet.au3 | Array.au3 (Optimized) | _UnixTimeParse() ]

#9 jpm

jpm

    a Real GUI/debug lover

  • Developers
  • 8,925 posts

Posted 05 January 2008 - 04:31 PM

This problem is here since 3.1.0.42 when Tylo introduce the array optimization.
Need Jon or Valik to analyze

#10 jpm

jpm

    a Real GUI/debug lover

  • Developers
  • 8,925 posts

Posted 09 January 2008 - 03:18 PM

Thanks,
Fixed 3.2.11.0




0 user(s) are reading this topic

0 members, 0 guests, 0 anonymous users