bug-bash
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: Passing variables by reference conflicts with local


From: Linda Walsh
Subject: Re: Passing variables by reference conflicts with local
Date: Wed, 25 Apr 2012 16:46:02 -0700
User-agent: Mozilla/5.0 (Windows; U; Windows NT 6.0; en-US; rv:1.8.1.24) Gecko/20100228 Lightning/0.9 Thunderbird/2.0.0.24 Mnenhy/0.7.6.666



Clark Wang wrote:

On Wed, May 5, 2010 at 01:57, Freddy Vulto <address@hidden> wrote:

It appears that `unset' is capable of traversing down the call-stack and
unsetting variables repeatedly:

   a=0 b=0 c=0 d=0 e=0
   _unset() { unset -v b c c d d d e; }
   t1() {
       local a=1 b=1 c=1 d=1
       t2
   }
   t2() {
       local a=2 b=2 c=2 d=2 e=2
       _unset
       echo a:$a b:$b c:$c d:$d e:$e
   }
   t1  # Outputs: a:2 b:1 c:0 d: e:0
       #            ^   ^   ^   ^  ^-- unset once (skipped t1)
       #            |   |   |   +----- unset thrice to global
       #            |   |   +--------- unset twice till global
       #            |   +------------- unset once till t1
       #            +----------------- unset not

It seems to work on bash-3.0, 3.2, 4.0 and 4.1.
Is this a bug or a feature?


When I revisit this 2 years old thread I don't understand why following
foo() function does not output the global var:

$ cat foo.sh
var=global
foo()
{
    local var=foo
    unset var
    echo foo: $var
}
bar_unset()
{
    unset var
}
bar()
{
    local var=bar
    bar_unset
    echo bar: $var
}
foo
bar
$ bash foo.sh
foo:
bar: global
$

In foo() it unsets its local var so why doesn't the subsequent $var refer
to the global var?

----
The above is pretty deep stuff, but I would guess from this:


Ishtar:> foo() { local var=foo; echo -n "type=\""; typeset -p var;echo -n "\""; unset var; typeset -p var ;echo foo: $var; }
Ishtar:> foo
type="declare -- var="foo"
"-bash: typeset: var: not found
foo:
----
I would guess (without looking at the codE), that
when you do a local, it creates another copy of 'var' at the end of an array.
like var[0][1]
so global is at 0, and local is at 1.
So let #=the index of the last position in the array so at
global var[#]='global',
local var[#]=foo, but 'local adds one to the var array, so it's going into 
var[1].
Now if you unset var[1], function foo still is using it's incremented value
of '#' (1) to tell you it has no value.

However, if you call a second function 'bar_unset', to unset the var
it deletes var[1], and sets # to 0,
so now when control returns to original
foo,
foo Can't assume # is unchanged (you've called another function,
it might have done something to # (the count of copies of var -- which it
did!)...
so it knows it did a "local", so it's copy of 'var' would be "last"
on the "var" value array --
but # has been reset to 0,
so now foo picks up var[0]...

That's just a guess based on how I might implement such behavior if I wanted
it to behave that way.

As to whether or not it is "correct" by some arbitrarily set standard or definition of "correct" -- that's a matter for nit-pickers and POSIXies. :-)

I'm sure someone more qualified with the internals can give a more accurate description of what happened, but that's my high level, "black-box" view.




reply via email to

[Prev in Thread] Current Thread [Next in Thread]