Hey all,

I think that I've identified a memory leak, but I'm not sure how to fix
it.  A little background:

The first thing I did was enable memory tracing in tcl by compiling it
with TCL_MEM_DEBUG enabled.  I then ran a script that I knew was giving
memory leaks and observed the output.  Here is the script:

proc tst_blend { } {
    ns_log Debug "inside tst_blend"
    set tsts   [java::new tcl.lang.NsjavaTests]
    set fields [java::new {String[]} {2}]
    $fields set 0 "last_name"
    $fields set 1 "email"
    set users [$tsts list_users $fields]
    set els   [$users elements]
    while { [$els hasMoreElements] } {
        set u   [$els nextElement]
        set u   [java::cast java.util.Hashtable $u]
        set kys [$u keys]
        while { [$kys hasMoreElements] } {
            set ky    [$kys nextElement]
            set value [$u get $ky]
            append page "<tr><td>[$ky toString]</td><td>[$value
toString]</td></tr>"
        }
    }

    ns_log Debug "exiting tst_blend"
}

proc ab2 { conn why } {

    ReturnHeaders
    ns_write "[ad_header {nsjava test}]"
    ns_log Debug "entering tst_blend"
    ns_log Debug "before memory info = [memory info]"
    memory trace on
    tst_blend
    memory trace off
    ns_log Debug "after memory info = [memory info]"
    ns_log Debug "outside tst_blend"
    ns_write "[ad_footer]"
}

ns_register_proc GET ab2 ab2


The memory trace on and memory trace off commands turn on the tracing of
all mallocs and frees within tcl.  I then collected the output and ran a
script to match up the mallocs and frees.  Here is a sample of the
output (I've added line numbers so I could build a cross-reference for
the allocs and frees):

1683  ckalloc  8ce23d8    24                 ./../generic/tclResult.c
834: freed at   1699
1684  ckalloc  8ce1f70    24                               javaList.c
402
1685  ckalloc  8ce2560     4                                 nsjava.c
1511
1686  ckalloc  8ce2598     4                ./../generic/tclListObj.c
922: freed at   1694
1687  ckalloc  8ce25d0     4                ./../generic/tclListObj.c
948: freed at   1692
1688  ckalloc  8ce1510    24                ./../generic/tclListObj.c
956: freed at   1693
1689  ckalloc  8ce2608    12                ./../generic/tclListObj.c
963: freed at   1695
1690  ckalloc  8ce2648     6                                javaObj.c
341: freed at   1691
1691   ckfree  8ce2648     6                                javaObj.c
369: alloc'd at 1690
1692   ckfree  8ce25d0     4                    ./../generic/tclObj.c
802: alloc'd at 1687
1693   ckfree  8ce1510    24                    ./../generic/tclObj.c
592: alloc'd at 1688
1694   ckfree  8ce2598     4                ./../generic/tclListObj.c
795: alloc'd at 1686
1695   ckfree  8ce2608    12                ./../generic/tclListObj.c
796: alloc'd at 1689
1696  ckalloc  8ce25a8    25                   ./../generic/tclHash.c
513: freed at   1899
1697  ckalloc  8ce25f8    52                  ./../generic/tclBasic.c
1649: freed at   1900
1698  ckalloc  8ce1510    24                                javaObj.c
279: freed at   1902
1699   ckfree  8ce23d8    24                 ./../generic/tclResult.c
355: alloc'd at 1683
1700   ckfree  8ce1968     9                    ./../generic/tclVar.c
1508: alloc'd at 1616
1701   ckfree  8ce2140    25                   ./../generic/tclHash.c
151: alloc'd at 1590
1702   ckfree  8ce2190    52                  ./../generic/tclBasic.c
2413: alloc'd at 1591
1703   ckfree  8ce2280    24                ./../generic/tclExecute.c
4924: alloc'd at 1617
1704   ckfree  8ce0ba0    24                    ./../generic/tclVar.c
1508: alloc'd at 1592
1705  ckalloc  8ce23d8     9                                 nsjava.c
1511: freed at   1876
1706  ckalloc  8ce1968    24                ./../generic/tclExecute.c
5030: freed at   1879
1707  ckalloc  8ce2280    24                 ./../generic/tclResult.c
834: freed at   1721
1708  ckalloc  8ce0ba0    24                               javaList.c
402
1709  ckalloc  8ce2660     9                                 nsjava.c
1511
1710  ckalloc  8ce26a0     4                ./../generic/tclListObj.c
922: freed at   1718
1711  ckalloc  8ce26d8     9                ./../generic/tclListObj.c
948: freed at   1716
1712  ckalloc  8ce2718    24                ./../generic/tclListObj.c
956: freed at   1717
1713  ckalloc  8ce2760    12                ./../generic/tclListObj.c
963: freed at   1719
1714  ckalloc  8ce27a0    16                                javaObj.c
341: freed at   1715
1715   ckfree  8ce27a0    16                                javaObj.c
369: alloc'd at 1714
1716   ckfree  8ce26d8     9                    ./../generic/tclObj.c
802: alloc'd at 1711
1717   ckfree  8ce2718    24                    ./../generic/tclObj.c
592: alloc'd at 1712
1718   ckfree  8ce26a0     4                ./../generic/tclListObj.c
795: alloc'd at 1710
1719   ckfree  8ce2760    12                ./../generic/tclListObj.c
796: alloc'd at 1713
1720  ckalloc  8ce26a0    24                                javaObj.c
279: freed at   1744
1721   ckfree  8ce2280    24                 ./../generic/tclResult.c
355: alloc'd at 1707
1722  ckalloc  8ce2280     9                                 nsjava.c
1511: freed at   1898
1723  ckalloc  8ce26e8    24                ./../generic/tclExecute.c
5030: freed at   1901
1724  ckalloc  8ce2730    24                 ./../generic/tclResult.c
834: freed at   1738
1725  ckalloc  8ce2778    24                               javaList.c
402
1726  ckalloc  8ce27c0     9                                 nsjava.c
1511
1727  ckalloc  8ce2800     4                ./../generic/tclListObj.c
922: freed at   1735

The complete trace is quite long, and I have only shown a small portion
of it here, but one thing is consistent, I never see the memory
allocated at javaList.c line 402 and nsjava.c line 1511 get freed up.
The function in javaList is Java_tcl_lang_TclList_splitList and the 24
byte allocation corresponds to a new Tcl_Obj.  The function called from
nsjava.c line 1511 is JavaGetString (nsjava is my hacked up version of
javaCmd.c which supports the aolserver interface) and the 9 bytes only
correspond to an allocation for a char array.   It's also important to
note that I'm using the reference counting changes suggested by  Jiang
Wu in a patch that he posted on the list here a while back.

It appears that the splitList method is only called from within the
setListFromAny method   The setListFromAny method is then used in most
of the TclList methods.  It's not clear to me why the TclList object and
the underlying Tcl_Obj wouldn't get cleaned up.

-Dan

----------------------------------------------------------------
The TclJava mailing list is sponsored by Scriptics Corporation.
To subscribe:    send mail to [EMAIL PROTECTED]  
                 with the word SUBSCRIBE as the subject.
To unsubscribe:  send mail to [EMAIL PROTECTED] 
                 with the word UNSUBSCRIBE as the subject.
To send to the list, send email to '[EMAIL PROTECTED]'. 
An archive is available at http://www.mail-archive.com/tcljava@scriptics.com

Reply via email to