Index: generic/tclCmdMZ.c
===================================================================
RCS file: /cvsroot/tcl/tcl/generic/tclCmdMZ.c,v
retrieving revision 1.82.2.23
diff -u -r1.82.2.23 tclCmdMZ.c
--- generic/tclCmdMZ.c	1 Nov 2005 20:19:26 -0000	1.82.2.23
+++ generic/tclCmdMZ.c	7 Nov 2005 21:31:44 -0000
@@ -23,7 +23,7 @@
 #include "tclCompile.h"
 
 /*
- * Structure used to hold information about variable traces:
+ * Structures used to hold information about variable traces:
  */
 
 typedef struct {
@@ -37,6 +37,11 @@
 				 * be larger than 4 bytes. */
 } TraceVarInfo;
 
+typedef struct {
+    VarTrace     trace;
+    TraceVarInfo tvar;
+} CompoundVarTrace;
+
 /*
  * Structure used to hold information about command traces:
  */
@@ -3678,10 +3683,24 @@
 	    command = Tcl_GetStringFromObj(objv[5], &commandLength);
 	    length = (size_t) commandLength;
 	    if ((enum traceOptions) optionIndex == TRACE_ADD) {
+		/*
+		 * This code essentially mallocs together the VarTrace and the
+		 * TraceVarInfo, then inlines the Tcl_TraceVar(). This is
+		 * necessary in order to have the TraceVarInfo to be freed 
+		 * automatically when the VarTrace is freed [Bug 1348775]
+		 */
+
+		CompoundVarTrace *compTracePtr;
 		TraceVarInfo *tvarPtr;
-		tvarPtr = (TraceVarInfo *) ckalloc((unsigned)
-			(sizeof(TraceVarInfo) - sizeof(tvarPtr->command)
+		Var *varPtr, *arrayPtr;
+		VarTrace *tracePtr;
+		int flagMask;
+
+		compTracePtr = (CompoundVarTrace *) ckalloc((unsigned)
+			(sizeof(CompoundVarTrace) - sizeof(tvarPtr->command)
 				+ length + 1));
+		tracePtr = &(compTracePtr->trace);
+		tvarPtr =  &(compTracePtr->tvar);
 		tvarPtr->flags = flags;
 		if (objv[0] == NULL) {
 		    tvarPtr->flags |= TCL_TRACE_OLD_STYLE;
@@ -3690,11 +3709,24 @@
 		flags |= TCL_TRACE_UNSETS | TCL_TRACE_RESULT_OBJECT;
 		strcpy(tvarPtr->command, command);
 		name = Tcl_GetString(objv[3]);
-		if (Tcl_TraceVar(interp, name, flags, TraceVarProc,
-			(ClientData) tvarPtr) != TCL_OK) {
-		    ckfree((char *) tvarPtr);
+		flagMask = TCL_GLOBAL_ONLY | TCL_NAMESPACE_ONLY;
+		varPtr = TclLookupVar(interp, name, NULL,
+			(flags & flagMask) | TCL_LEAVE_ERR_MSG,
+			"trace", /*createPart1*/ 1, /*createPart2*/ 1, &arrayPtr);
+		if (varPtr == NULL) {
+		    ckfree((char *) tracePtr);
 		    return TCL_ERROR;
 		}
+		flagMask = TCL_TRACE_READS | TCL_TRACE_WRITES | TCL_TRACE_UNSETS | 
+		    TCL_TRACE_ARRAY | TCL_TRACE_RESULT_DYNAMIC | TCL_TRACE_RESULT_OBJECT;
+#ifndef TCL_REMOVE_OBSOLETE_TRACES
+		flagMask |= TCL_TRACE_OLD_STYLE;
+#endif
+		tracePtr->traceProc = TraceVarProc;
+		tracePtr->clientData = (ClientData) tvarPtr;
+		tracePtr->flags	= flags & flagMask;
+		tracePtr->nextPtr = varPtr->tracePtr;
+		varPtr->tracePtr = tracePtr;
 	    } else {
 		/*
 		 * Search through all of our traces on this variable to
@@ -3715,7 +3747,6 @@
 			Tcl_UntraceVar2(interp, name, NULL, 
 			  flags | TCL_TRACE_UNSETS | TCL_TRACE_RESULT_OBJECT,
 				TraceVarProc, clientData);
-			Tcl_EventuallyFree((ClientData) tvarPtr, TCL_DYNAMIC);
 			break;
 		    }
 		}
@@ -4707,8 +4738,6 @@
      * freed while we still need it.
      */
 
-    Tcl_Preserve((ClientData) tvarPtr);
-
     result = NULL;
     if ((tvarPtr->flags & flags) && !(flags & TCL_INTERP_DESTROYED)) {
 	if (tvarPtr->length != (size_t) 0) {
@@ -4783,9 +4812,7 @@
 	    Tcl_DecrRefCount(errMsgObj);
 	    result = NULL;
 	}
-	Tcl_EventuallyFree((ClientData) tvarPtr, TCL_DYNAMIC);
     }
-    Tcl_Release((ClientData) tvarPtr);
     return result;
 }
 
