*** tcl8.3.2/generic/tclCmdMZ.c Mon Apr 10 17:08:26 2000 --- tcl8.3.2-patch/generic/tclCmdMZ.c Thu Aug 24 21:03:51 2000 *************** *** 2626,2633 **** TraceVarProc, clientData); if (tvarPtr->errMsg != NULL) { ckfree(tvarPtr->errMsg); } ! ckfree((char *) tvarPtr); break; } } --- 2626,2634 ---- TraceVarProc, clientData); if (tvarPtr->errMsg != NULL) { ckfree(tvarPtr->errMsg); + tvarPtr->errMsg = NULL; } ! Tcl_EventuallyFree((ClientData) tvarPtr, TCL_DYNAMIC); break; } } *************** *** 2729,2734 **** --- 2730,2745 ---- int code; Tcl_DString cmd; + /* + * We might call Tcl_Eval() below, and that might evaluate + * [trace vdelete] which might try to free tvarPtr. We want + * to use tvarPtr until the end of this function, so we use + * Tcl_Preserve() and Tcl_Release() to be sure it is not + * freed while we still need it. + */ + + Tcl_Preserve((ClientData) tvarPtr); + result = NULL; if (tvarPtr->errMsg != NULL) { ckfree(tvarPtr->errMsg); *************** *** 2784,2792 **** result = NULL; if (tvarPtr->errMsg != NULL) { ckfree(tvarPtr->errMsg); } ! ckfree((char *) tvarPtr); } return result; } ^L --- 2795,2810 ---- result = NULL; if (tvarPtr->errMsg != NULL) { ckfree(tvarPtr->errMsg); + tvarPtr->errMsg = NULL; } ! Tcl_EventuallyFree((ClientData) tvarPtr, TCL_DYNAMIC); } + + /* + * Match for Tcl_Preserve() near start of this function. + */ + + Tcl_Release((ClientData) tvarPtr); return result; } ^L