2015-02-05 14:52 GMT-02:00 Paulo César Pereira de Andrade
<[email protected]>:
Sorry for chatting with myself.
First, to more easily see the leak, ksh must be built with
"-D_AST_std_malloc=1" in CFLAGS, then check it with
valgrind.
A simplified test case:
---8<---
typeset -A stuff
typeset -lui i=0
for (( i=0; i<1000; i++ ))
do
unset stuff[xyz]
typeset -A stuff[xyz]
stuff[xyz][elem0]="data0"
stuff[xyz][elem1]="data1"
stuff[xyz][elem2]="data2"
stuff[xyz][elem3]="data3"
stuff[xyz][elem4]="data4"
done
---8<---
Under valgrid it will tell something like this:
---8<---
==31100== 669,330 (102,336 direct, 566,994 indirect) bytes in 984
blocks are definitely lost in loss record 145 of 145
==31100== at 0x4C2A1D4: calloc (in
/usr/lib64/valgrind/vgpreload_memcheck-amd64-linux.so)
==31100== by 0x418253: nv_associative (array.c:1674)
==31100== by 0x41632A: nv_setarray (array.c:1000)
==31100== by 0x4893B0: setall (typeset.c:709)
==31100== by 0x4883F9: b_typeset (typeset.c:457)
[...]
==31100== LEAK SUMMARY:
==31100== definitely lost: 102,336 bytes in 985 blocks
==31100== indirectly lost: 566,994 bytes in 11,004 blocks
==31100== possibly lost: 4,941 bytes in 4 blocks
==31100== still reachable: 217,645 bytes in 154 blocks
==31100== suppressed: 0 bytes in 0 blocks
---8<---
(with the original test case it would leak over 1G)
But after further investigation, I am no longer convinced it
is "really" a bug per se (but still a bug due to not releasing memory
that becomes unreachable, and that is my next line of search
for a solution to this issue). Because ksh manual page says:
---8<---
unset [ -fnv ] vname ...
The variables given by the list of vnames are unassigned, i.e.,
except for sub-variables within a type, their values and
attributes are erased. For sub-variables of a type, the values
are reset to the default value from the type definition. Read‐
only variables cannot be unset. If the -f option is set, then
the names refer to function names. If the -v option is set,
then the names refer to variable names. The -f option overrides
-v. If -n is set and name is a name reference, then name will
be unset rather than the variable that it references. The
default is equivalent to -v. Unsetting LINENO, MAILCHECK,
OPTARG, OPTIND, RANDOM, SECONDS, TMOUT, and _ removes their spe‐
cial meaning even if they are subsequently assigned to.
---8<---
So, it looks like some special interpretation must be required
here. The test cases abuses it to show its point, but it is
assuming that:
---8<---
unset stuff[xyz]
---8<---
would be kind of an alias to:
---8<---
unset stuff[xyz][elem0]
unset stuff[xyz][elem1]
unset stuff[xyz][elem2]
unset stuff[xyz][elem3]
unset stuff[xyz][elem4]
unset stuff[xyz]
---8<---
that does not leak. The other case that does not leak
is "unset -f stuff[xyz]", but it is because it does nothing,
i.e. the same as commenting the "unset x[yz]" line.
I can get it to kind of do what is supposed by the test
case with this patch:
---8<---
diff -up ksh-20120801/src/cmd/ksh93/bltins/typeset.c.orig
ksh-20120801/src/cmd/ksh93/bltins/typeset.c
--- ksh-20120801/src/cmd/ksh93/bltins/typeset.c.orig 2015-02-05
17:53:47.126072019 -0200
+++ ksh-20120801/src/cmd/ksh93/bltins/typeset.c 2015-02-05
17:53:50.133069136 -0200
@@ -1215,7 +1215,7 @@ static int unall(int argc, char **argv,
np = sh_fsearch(shp,name,nflag?HASH_NOSCOPE:0);
if(!np)
#endif /* SHOPT_NAMESPACE */
- np=nv_open(name,troot,NV_NOADD|nflag);
+ np=nv_open(name,troot,NV_NOADD|NV_ARRAY|nflag);
}
else
{
---8<---
but that will unset all stuff[*], not just stuff[xyz]. For example, with
the above, tests would fail like this:
---8<---
test arith(C.UTF-8) begins at 2015-02-05+19:13:52
arith.sh[708]: typeset: cannot change associative array A to index array
test arith(C.UTF-8) failed at 2015-02-05+19:13:52 with exit code 1 [
201 tests 1 error ]
test arith(shcomp) begins at 2015-02-05+19:13:52
/tmp/tmp.upsGR4Aapu/shcomp-arith.ksh[708]: typeset: cannot change
associative array A to index array
test arith(shcomp) failed at 2015-02-05+19:13:52 with exit code 1 [
201 tests 1 error ]
test arrays begins at 2015-02-05+19:13:52
arrays.sh[84]: number of elements of y is not 6
arrays.sh[87]: string length of unset element is not 0
arrays.sh[106]: number of elements of left in variable foo is not 0
arrays.sh[114]: number of elements of left in variable foo again is not 0
arrays.sh[395]: ${!var[sub]} should be var[sub]
arrays.sh[427]: subscript not evaluated for unset variable
arrays.sh[430]: typeset: cannot change associative array foo to index array
test arrays failed at 2015-02-05+19:13:52 with exit code 1 [ 145 tests 1 error ]
test arrays(C.UTF-8) begins at 2015-02-05+19:13:52
arrays.sh[84]: number of elements of y is not 6
arrays.sh[87]: string length of unset element is not 0
arrays.sh[106]: number of elements of left in variable foo is not 0
arrays.sh[114]: number of elements of left in variable foo again is not 0
arrays.sh[395]: ${!var[sub]} should be var[sub]
arrays.sh[427]: subscript not evaluated for unset variable
arrays.sh[430]: typeset: cannot change associative array foo to index array
test arrays(C.UTF-8) failed at 2015-02-05+19:13:52 with exit code 1 [
145 tests 1 error ]
test arrays(shcomp) begins at 2015-02-05+19:13:52
shcomp-arrays.ksh[84]: number of elements of y is not 6
shcomp-arrays.ksh[87]: string length of unset element is not 0
shcomp-arrays.ksh[106]: number of elements of left in variable foo is not 0
shcomp-arrays.ksh[114]: number of elements of left in variable foo
again is not 0
shcomp-arrays.ksh[395]: ${!var[sub]} should be var[sub]
shcomp-arrays.ksh[427]: subscript not evaluated for unset variable
/tmp/tmp.upsGR4Aapu/shcomp-arrays.ksh[430]: typeset: cannot change
associative array foo to index array
test arrays(shcomp) failed at 2015-02-05+19:13:52 with exit code 1 [
145 tests 1 error ]
test bracket begins at 2015-02-05+19:15:16
bracket.sh[309]: ${foo[1]+x} should be empty
bracket.sh[311]: bar[1] should not be set
bracket.sh[315]: z[1] should not be set
bracket.sh[320]: y[1] should not be set
test bracket failed at 2015-02-05+19:15:22 with exit code 1 [ 118
tests 1 error ]
test bracket(C.UTF-8) begins at 2015-02-05+19:15:22
bracket.sh[309]: ${foo[1]+x} should be empty
bracket.sh[311]: bar[1] should not be set
bracket.sh[315]: z[1] should not be set
bracket.sh[320]: y[1] should not be set
test bracket(C.UTF-8) failed at 2015-02-05+19:15:27 with exit code 1 [
118 tests 1 error ]
test bracket(shcomp) begins at 2015-02-05+19:15:27
shcomp-bracket.ksh[309]: ${foo[1]+x} should be empty
shcomp-bracket.ksh[311]: bar[1] should not be set
shcomp-bracket.ksh[315]: z[1] should not be set
shcomp-bracket.ksh[320]: y[1] should not be set
test bracket(shcomp) failed at 2015-02-05+19:15:32 with exit code 4 [
118 tests 4 errors ]
---8<---
Any comments?
Thanks,
Paulo
_______________________________________________
ast-users mailing list
[email protected]
http://lists.research.att.com/mailman/listinfo/ast-users