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

Reply via email to