• Tcl-C API: What's wrong with THIS =?UTF-8?B?VGNsX0RlY3JSZWZDb3VudCA/?=

    From aldo.w.buratti@aldo.w.buratti@gmail.com (abu) to comp.lang.tcl on Wed Mar 5 20:41:25 2025
    From Newsgroup: comp.lang.tcl

    I have some unexèpected result with this (over-simplified) C code (using
    the Tcl-C API), and I don't understandard what's wrong.

    Please could you tell me what's wrong with this Tcl-C code ?

    --
    This is (in plain Tcl) what I'm trying to achive.
    This may seem silly, but it's just an oversimplified case.

    ----
    proc fun {} {
    # build a list of values
    set A [list]
    foreach element {100.0 200.0 300.0} { lappend A $element }

    # -- now extract and return the 1st element
    set v [lindex $A 0]
    return $v
    }
    ----
    And here's its adaption in C (using the Tcl-C API)

    ---
    int CMD_fun { ClientData clientData, Tcl_Interp *interp, int argc, const
    char *argv[]) {
    Tcl_Obj* aList = Tcl_NewListObj(0,NULL);
    for (int i=1 ; i <= 3; ++i) {
    Tcl_ListObjAppendElement(interp, aList , Tcl_NewDoubleObj(i*100.0));
    }

    //extract the 1st element (-> 100.0) and incr its RefCount
    Tcl_Obj* resultObj;

    Tcl_ListObjIndex(interp,aList,0,&resultObj);
    Tcl_IncrRefCount(resultObj);

    // free aList
    Tcl_DecrRefCount(aList); // the listObj, and all its elements are released, but the first

    Tcl_SetObjResult( interp, resultObj );
    return TCL_OK;
    }
    ..
    Tcl_CreateObjCommand( interp, "cfun" , CMD_fun, (ClientData)NULL, (Tcl_CmdDeleteProc *)NULL) ;
    ..
    ---
    This works as expected (return 100.0), but if called 100.000 times,
    I see an abnormal growth in memory (Megabytes).

    What's wrong ?
    --- Synchronet 3.20c-Linux NewsLink 1.2
  • From Schelte@nospam@wanadoo.nl to comp.lang.tcl on Thu Mar 6 10:05:53 2025
    From Newsgroup: comp.lang.tcl

    On 05/03/2025 21:41, abu wrote:
    This works as expected  (return 100.0), but if called 100.000 times,
    I see an abnormal growth in memory (Megabytes).

    What's wrong ?

    For one thing, your reference count on resultObj is too high. You did an explicit Tcl_IncrRefCount() and Tcl_SetObjResult() increments it again.
    It now has a count of 2. When the code that invoked the cfun command is
    done with the result, it lowers the reference count by one. But that
    does not free the Tcl_Obj, because it still has a reference count of 1.
    As a Tcl_Obj takes 24 bytes on a 32-bit system (and more on a 64-bit
    system), this would add up to a few megabytes when called 100.000 times.

    Either skip the Tcl_IncrRefCount() and run Tcl_SetObjResult() before the Tcl_DecrRefCount() on aList, or do a Tcl_DecrRefCount() on resultObj
    after the Tcl_SetObjResult() call.


    Schelte.

    --- Synchronet 3.20c-Linux NewsLink 1.2
  • From aldo.w.buratti@aldo.w.buratti@gmail.com (abu) to comp.lang.tcl on Thu Mar 6 12:54:34 2025
    From Newsgroup: comp.lang.tcl

    Thank you. It was so simple !
    Now it works !
    Thank you again.

    Aldo
    --- Synchronet 3.20c-Linux NewsLink 1.2