[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 <fvulto@gmail.com> 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.
Re: Passing variables by reference conflicts with local, Chet Ramey, 2012/04/28