2015-02-05 14:52 GMT-02:00 Paulo César Pereira de Andrade <paulo.cesar.pereira.de.andr...@gmail.com>:
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 ast-users@lists.research.att.com http://lists.research.att.com/mailman/listinfo/ast-users