Attachment "final.patch" to
ticket [487677ffff]
added by
dgp
2001-12-29 06:36:42.
Index: ChangeLog
===================================================================
RCS file: /cvsroot/tcl/tcl/ChangeLog,v
retrieving revision 1.769
diff -u -u -r1.769 ChangeLog
--- ChangeLog 2001/12/27 22:46:12 1.769
+++ ChangeLog 2001/12/28 23:32:21
@@ -1,3 +1,23 @@
+2001-12-29 Don Porter <[email protected]>
+
+ * generic/tclCkalloc.c (MemoryCmd, TclFinalizeMemorySubsystem):
+ Added the [memory onexit] command, intended to replace [checkmem].
+
+ * doc/DumpActiveMemory.3:
+ * doc/memory.n: Updated documentation for [memory] and related
+ matters. [Bug 487677]
+
+ * mac/tclMacBOAMain.c (Tcl_Main, CheckmemCmd): Removed all the
+ machinery for the [checkmem] command that is completely duplicated
+ by code in generic/tclCkalloc.c.
+
+ * generic/tclBinary.c:
+ * generic/tclListObj.c:
+ * generic/tclObj.c:
+ * generic/tclStringObj.c: Removed references to [checkmem] in
+ comments, referencing [memory active] instead, since it is
+ documented.
+
2001-12-28 Daniel Steffen <[email protected]>
* mac/tclMacInit.c:
@@ -103,7 +123,6 @@
* doc/CrtInterp.3:
* generic/tclBasic.c: docs and comments corrections [Bug 493412]
Bug & patch by Don Porter.
-
2001-12-14 Donal K. Fellows <[email protected]>
Index: doc/DumpActiveMemory.3
===================================================================
RCS file: /cvsroot/tcl/tcl/doc/DumpActiveMemory.3,v
retrieving revision 1.4
diff -u -u -r1.4 DumpActiveMemory.3
--- doc/DumpActiveMemory.3 2001/05/03 23:52:56 1.4
+++ doc/DumpActiveMemory.3 2001/12/28 23:32:21
@@ -37,8 +37,9 @@
.SH DESCRIPTION
These functions provide access to Tcl memory debugging information.
-They are only available when Tcl has been compiled with
-\fBTCL_MEM_DEBUG\fR defined at compile-time.
+They are only functional when Tcl has been compiled with
+\fBTCL_MEM_DEBUG\fR defined at compile-time. When \fBTCL_MEM_DEBUG\fR
+is not defined, these functions are all no-ops.
.PP
\fBTcl_DumpActiveMemory\fR will output a list of all currently
allocated memory to the specified file. The information output for
@@ -49,8 +50,8 @@
interpreter has been deleted.
.PP
\fBTcl_InitMemory\fR adds the Tcl \fBmemory\fR command to the
-interpreter given by \fIinterp\fR. It is called by \fBTcl_Main\fR
-when Tcl has been compiled with \fBTCL_MEM_DEBUG\fR defined.
+interpreter given by \fIinterp\fR. \fBTcl_InitMemory\fR is called
+by \fBTcl_Main\fR.
.PP
\fBTcl_ValidateAllMemory\fR forces a validation of the guard zones of
all currently allocated blocks of memory. Normally validation of a
Index: doc/memory.n
===================================================================
RCS file: /cvsroot/tcl/tcl/doc/memory.n,v
retrieving revision 1.3
diff -u -u -r1.3 memory.n
--- doc/memory.n 2000/09/07 14:27:49 1.3
+++ doc/memory.n 2001/12/28 23:32:22
@@ -19,15 +19,42 @@
debugging capabilities. The memory command has several suboptions, which are
described below. It is only available when Tcl has been compiled with
memory debugging enabled (when \fBTCL_MEM_DEBUG\fR is defined at
-compile time).
+compile time), and after \fBTcl_InitMemory\fR has been called.
.TP
+\fBmemory active\fR \fIfile\fR
+Write a list of all currently allocated memory to the specified \fIfile\fR.
+.TP
+\fBmemory break_on_malloc\fR \fIcount\fR
+After the \fIcount\fR allocations have been performed, \fBckalloc\fR
+outputs a message to this effect and that it is now attempting to enter
+the C debugger. Tcl will then issue a \fISIGINT\fR signal against itself.
+If you are running Tcl under a C debugger, it should then enter the debugger
+command mode.
+.TP
\fBmemory info\fR
-Produces a report containing the total allocations and frees since
+Returns a report containing the total allocations and frees since
Tcl began, the current packets allocated (the current
number of calls to \fBckalloc\fR not met by a corresponding call
to \fBckfree\fR), the current bytes allocated, and the maximum number
of packets and bytes allocated.
.TP
+\fB memory init [on|off]\fR
+Turn on or off the pre-initialization of all allocated memory
+with bogus bytes. Useful for detecting the use of uninitialized values.
+.TP
+\fBmemory onexit\fR \fIfile\fR
+Causes a list of all allocated memory to be written to the specified \fIfile\fR
+during the finalization of Tcl's memory subsystem. Useful for checking
+that memory is properly cleaned up during process exit.
+.TP
+\fBmemory tag\fR \fIstring\fR
+Each packet of memory allocated by \fBckalloc\fR can have associated
+with it a string-valued tag. In the lists of allocated memory generated
+by \fBmemory active\fR and \fBmemory onexit\fR, the tag for each packet
+is printed along with other information about the packet. The
+\fBmemory tag\fR command sets the tag value for subsequent calls
+to \fBckalloc\fR to be \fIstring\fR.
+.TP
\fBmemory trace [on|off]\fR
.br
Turns memory tracing on or off. When memory tracing is on, every call
@@ -35,23 +62,13 @@
\fIstderr\fR, consisting of the word \fIckalloc\fR, followed by the
address returned, the amount of memory allocated, and the C filename
and line number of the code performing the allocation. For example:
+.RS
.CS
ckalloc 40e478 98 tclProc.c 1406
.CE
Calls to \fBckfree\fR are traced in the same manner.
+.RE
.TP
-\fBmemory validate [on|off]\fR
-Turns memory validation on or off. When memory validation is enabled,
-on every call to \fBckalloc\fR or \fBckfree\fR, the guard zones are
-checked for every piece of memory currently in existence that was
-allocated by \fBckalloc\fR. This has a large performance impact and
-should only be used when overwrite problems are strongly suspected.
-The advantage of enabling memory validation is that a guard zone
-overwrite can be detected on the first call to \fBckalloc\fR or
-\fBckfree\fR after the overwrite occurred, rather than when the
-specific memory with the overwritten guard zone(s) is freed, which may
-occur long after the overwrite occurred.
-.TP
\fBmemory trace_on_at_malloc\fR \fIcount\fR
Enable memory tracing after \fIcount\fR \fBckalloc\fR's have been performed.
For example, if you enter \fBmemory trace_on_at_malloc 100\fR,
@@ -63,15 +80,17 @@
the problem sets in. The current number of memory allocations that have
occurred since Tcl started is printed on a guard zone failure.
.TP
-\fBmemory break_on_malloc\fR \fIcount\fR
-After the \fBcount\fR allocations have been performed, \fBckalloc\fR's
-output a message to this effect and that it is now attempting to enter
-the C debugger. Tcl will then issue a \fISIGINT\fR signal against itself.
-If you are running Tcl under a C debugger, it should then enter the debugger
-command mode.
-.TP
-\fB memory display\fR \fIfile\fR
-Write a list of all currently allocated memory to the specified file.
+\fBmemory validate [on|off]\fR
+Turns memory validation on or off. When memory validation is enabled,
+on every call to \fBckalloc\fR or \fBckfree\fR, the guard zones are
+checked for every piece of memory currently in existence that was
+allocated by \fBckalloc\fR. This has a large performance impact and
+should only be used when overwrite problems are strongly suspected.
+The advantage of enabling memory validation is that a guard zone
+overwrite can be detected on the first call to \fBckalloc\fR or
+\fBckfree\fR after the overwrite occurred, rather than when the
+specific memory with the overwritten guard zone(s) is freed, which may
+occur long after the overwrite occurred.
.SH "SEE ALSO"
ckalloc, ckfree, Tcl_ValidateAllMemory, Tcl_DumpActiveMemory, TCL_MEM_DEBUG
Index: generic/tclBinary.c
===================================================================
RCS file: /cvsroot/tcl/tcl/generic/tclBinary.c,v
retrieving revision 1.9
diff -u -u -r1.9 tclBinary.c
--- generic/tclBinary.c 2001/11/29 15:38:40 1.9
+++ generic/tclBinary.c 2001/12/28 23:32:22
@@ -180,8 +180,8 @@
* TCL_MEM_DEBUG is defined. It is the same as the Tcl_NewByteArrayObj
* above except that it calls Tcl_DbCkalloc directly with the file name
* and line number from its caller. This simplifies debugging since then
- * the checkmem command will report the correct file name and line number
- * when reporting objects that haven't been freed.
+ * the [memory active] command will report the correct file name and line
+ * number when reporting objects that haven't been freed.
*
* When TCL_MEM_DEBUG is not defined, this procedure just returns the
* result of calling Tcl_NewByteArrayObj.
Index: generic/tclCkalloc.c
===================================================================
RCS file: /cvsroot/tcl/tcl/generic/tclCkalloc.c,v
retrieving revision 1.13
diff -u -u -r1.13 tclCkalloc.c
--- generic/tclCkalloc.c 2001/12/18 15:21:20 1.13
+++ generic/tclCkalloc.c 2001/12/28 23:32:22
@@ -111,6 +111,7 @@
char *tclMemDumpFileName = NULL;
+static char *onExitMemDumpFileName = NULL;
static char dumpFile[100]; /* Records where to dump memory allocation
* information. */
@@ -304,7 +305,7 @@
* information will be written to stderr.
*
* Results:
- * Return TCL_ERROR if an error accessing the file occures, `errno'
+ * Return TCL_ERROR if an error accessing the file occurs, `errno'
* will have the file error number left in it.
*----------------------------------------------------------------------
*/
@@ -759,11 +760,14 @@
* MemoryCmd --
* Implements the Tcl "memory" command, which provides Tcl-level
* control of Tcl memory debugging information.
+ * memory active $file
+ * memory break_on_malloc $count
* memory info
- * memory display
- * memory break_on_malloc count
- * memory trace_on_at_malloc count
+ * memory init on|off
+ * memory onexit $file
+ * memory tag $string
* memory trace on|off
+ * memory trace_on_at_malloc $count
* memory validate on|off
*
* Results:
@@ -789,10 +793,10 @@
return TCL_ERROR;
}
- if (strcmp(argv[1],"active") == 0) {
+ if ((strcmp(argv[1],"active") == 0) || (strcmp(argv[1],"display") == 0)) {
if (argc != 3) {
Tcl_AppendResult(interp, "wrong # args: should be \"",
- argv[0], " active file\"", (char *) NULL);
+ argv[0], " ", argv[1], " file\"", (char *) NULL);
return TCL_ERROR;
}
fileName = Tcl_TranslateFileName(interp, argv[2], &buffer);
@@ -818,14 +822,14 @@
return TCL_OK;
}
if (strcmp(argv[1],"info") == 0) {
- char buffer[400];
- sprintf(buffer, "%-25s %10d\n%-25s %10d\n%-25s %10d\n%-25s %10d\n%-25s %10d\n%-25s %10d\n",
+ char buf[400];
+ sprintf(buf, "%-25s %10d\n%-25s %10d\n%-25s %10d\n%-25s %10d\n%-25s %10d\n%-25s %10d\n",
"total mallocs", total_mallocs, "total frees", total_frees,
"current packets allocated", current_malloc_packets,
"current bytes allocated", current_bytes_malloced,
"maximum packets allocated", maximum_malloc_packets,
"maximum bytes allocated", maximum_bytes_malloced);
- Tcl_SetResult(interp, buffer, TCL_VOLATILE);
+ Tcl_SetResult(interp, buf, TCL_VOLATILE);
return TCL_OK;
}
if (strcmp(argv[1],"init") == 0) {
@@ -835,6 +839,21 @@
init_malloced_bodies = (strcmp(argv[2],"on") == 0);
return TCL_OK;
}
+ if (strcmp(argv[1],"onexit") == 0) {
+ if (argc != 3) {
+ Tcl_AppendResult(interp, "wrong # args: should be \"",
+ argv[0], " onexit file\"", (char *) NULL);
+ return TCL_ERROR;
+ }
+ fileName = Tcl_TranslateFileName(interp, argv[2], &buffer);
+ if (fileName == NULL) {
+ return TCL_ERROR;
+ }
+ onExitMemDumpFileName = dumpFile;
+ strcpy(onExitMemDumpFileName,fileName);
+ Tcl_DStringFree(&buffer);
+ return TCL_OK;
+ }
if (strcmp(argv[1],"tag") == 0) {
if (argc != 3) {
Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
@@ -875,7 +894,7 @@
}
Tcl_AppendResult(interp, "bad option \"", argv[1],
- "\": should be active, break_on_malloc, info, init, ",
+ "\": should be active, break_on_malloc, info, init, onexit, ",
"tag, trace, trace_on_at_malloc, or validate", (char *) NULL);
return TCL_ERROR;
@@ -1216,6 +1235,8 @@
Tcl_MutexLock(ckallocMutexPtr);
if (tclMemDumpFileName != NULL) {
Tcl_DumpActiveMemory(tclMemDumpFileName);
+ } else if (onExitMemDumpFileName != NULL) {
+ Tcl_DumpActiveMemory(onExitMemDumpFileName);
}
if (curTagPtr != NULL) {
TclpFree((char *) curTagPtr);
Index: generic/tclListObj.c
===================================================================
RCS file: /cvsroot/tcl/tcl/generic/tclListObj.c,v
retrieving revision 1.11
diff -u -u -r1.11 tclListObj.c
--- generic/tclListObj.c 2001/11/16 21:41:14 1.11
+++ generic/tclListObj.c 2001/12/28 23:32:22
@@ -132,9 +132,9 @@
* TCL_MEM_DEBUG is defined. It creates new list objects. It is the
* same as the Tcl_NewListObj procedure above except that it calls
* Tcl_DbCkalloc directly with the file name and line number from its
- * caller. This simplifies debugging since then the checkmem command
- * will report the correct file name and line number when reporting
- * objects that haven't been freed.
+ * caller. This simplifies debugging since then the [memory active]
+ * command will report the correct file name and line number when
+ * reporting objects that haven't been freed.
*
* When TCL_MEM_DEBUG is not defined, this procedure just returns the
* result of calling Tcl_NewListObj.
Index: generic/tclObj.c
===================================================================
RCS file: /cvsroot/tcl/tcl/generic/tclObj.c,v
retrieving revision 1.26
diff -u -u -r1.26 tclObj.c
--- generic/tclObj.c 2001/11/23 01:28:58 1.26
+++ generic/tclObj.c 2001/12/28 23:32:22
@@ -534,7 +534,7 @@
* empty string. It is the same as the Tcl_NewObj procedure above
* except that it calls Tcl_DbCkalloc directly with the file name and
* line number from its caller. This simplifies debugging since then
- * the checkmem command will report the correct file name and line
+ * the [memory active] command will report the correct file name and line
* number when reporting objects that haven't been freed.
*
* When TCL_MEM_DEBUG is not defined, this procedure just returns the
@@ -936,9 +936,9 @@
* TCL_MEM_DEBUG is defined. It creates new boolean objects. It is the
* same as the Tcl_NewBooleanObj procedure above except that it calls
* Tcl_DbCkalloc directly with the file name and line number from its
- * caller. This simplifies debugging since then the checkmem command
- * will report the correct file name and line number when reporting
- * objects that haven't been freed.
+ * caller. This simplifies debugging since then the [memory active]
+ * command will report the correct file name and line number when
+ * reporting objects that haven't been freed.
*
* When TCL_MEM_DEBUG is not defined, this procedure just returns the
* result of calling Tcl_NewBooleanObj.
@@ -1294,9 +1294,9 @@
* TCL_MEM_DEBUG is defined. It creates new double objects. It is the
* same as the Tcl_NewDoubleObj procedure above except that it calls
* Tcl_DbCkalloc directly with the file name and line number from its
- * caller. This simplifies debugging since then the checkmem command
- * will report the correct file name and line number when reporting
- * objects that haven't been freed.
+ * caller. This simplifies debugging since then the [memory active]
+ * command will report the correct file name and line number when
+ * reporting objects that haven't been freed.
*
* When TCL_MEM_DEBUG is not defined, this procedure just returns the
* result of calling Tcl_NewDoubleObj.
@@ -1925,8 +1925,8 @@
* When the core is compiled with TCL_MEM_DEBUG defined,
* Tcl_DbNewLongObj calls Tcl_DbCkalloc directly with the file name and
* line number from its caller. This simplifies debugging since then
- * the checkmem command will report the caller's file name and line
- * number when reporting objects that haven't been freed.
+ * the [memory active] command will report the caller's file name and
+ * line number when reporting objects that haven't been freed.
*
* Otherwise, when the core is compiled without TCL_MEM_DEBUG defined,
* this procedure just returns the result of calling Tcl_NewLongObj.
Index: generic/tclStringObj.c
===================================================================
RCS file: /cvsroot/tcl/tcl/generic/tclStringObj.c,v
retrieving revision 1.21
diff -u -u -r1.21 tclStringObj.c
--- generic/tclStringObj.c 2001/05/15 21:30:46 1.21
+++ generic/tclStringObj.c 2001/12/28 23:32:23
@@ -219,9 +219,9 @@
* TCL_MEM_DEBUG is defined. It creates new string objects. It is the
* same as the Tcl_NewStringObj procedure above except that it calls
* Tcl_DbCkalloc directly with the file name and line number from its
- * caller. This simplifies debugging since then the checkmem command
- * will report the correct file name and line number when reporting
- * objects that haven't been freed.
+ * caller. This simplifies debugging since then the [memory active]
+ * command will report the correct file name and line number when
+ * reporting objects that haven't been freed.
*
* When TCL_MEM_DEBUG is not defined, this procedure just returns the
* result of calling Tcl_NewStringObj.
Index: mac/tclMacBOAMain.c
===================================================================
RCS file: /cvsroot/tcl/tcl/mac/tclMacBOAMain.c,v
retrieving revision 1.3
diff -u -u -r1.3 tclMacBOAMain.c
--- mac/tclMacBOAMain.c 1999/04/16 00:47:19 1.3
+++ mac/tclMacBOAMain.c 2001/12/28 23:32:23
@@ -49,22 +49,10 @@
static Tcl_Interp *interp; /* Interpreter for application. */
-#ifdef TCL_MEM_DEBUG
-static char dumpFile[100]; /* Records where to dump memory allocation
- * information. */
-static int quitFlag = 0; /* 1 means "checkmem" command was called,
- * so the application should quit and dump
- * memory allocation information. */
-#endif
-
/*
* Forward references for procedures defined later in this file:
*/
-#ifdef TCL_MEM_DEBUG
-static int CheckmemCmd _ANSI_ARGS_((ClientData clientData,
- Tcl_Interp *interp, int argc, char *argv[]));
-#endif
void TclMacDoNotification(char *mssg);
void TclMacNotificationResponse(NMRecPtr nmRec);
int Tcl_MacBGNotifyObjCmd(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const *objv);
@@ -108,11 +96,7 @@
Tcl_FindExecutable(argv[0]);
interp = Tcl_CreateInterp();
-#ifdef TCL_MEM_DEBUG
Tcl_InitMemory(interp);
- Tcl_CreateCommand(interp, "checkmem", CheckmemCmd, (ClientData) 0,
- (Tcl_CmdDeleteProc *) NULL);
-#endif
/*
* Make command-line arguments available in the Tcl variables "argc"
@@ -318,44 +302,3 @@
}
-
-/*
- *----------------------------------------------------------------------
- *
- * CheckmemCmd --
- *
- * This is the command procedure for the "checkmem" command, which
- * causes the application to exit after printing information about
- * memory usage to the file passed to this command as its first
- * argument.
- *
- * Results:
- * Returns a standard Tcl completion code.
- *
- * Side effects:
- * None.
- *
- *----------------------------------------------------------------------
- */
-#ifdef TCL_MEM_DEBUG
-
- /* ARGSUSED */
-static int
-CheckmemCmd(clientData, interp, argc, argv)
- ClientData clientData; /* Not used. */
- Tcl_Interp *interp; /* Interpreter for evaluation. */
- int argc; /* Number of arguments. */
- char *argv[]; /* String values of arguments. */
-{
- extern char *tclMemDumpFileName;
- if (argc != 2) {
- Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
- " fileName\"", (char *) NULL);
- return TCL_ERROR;
- }
- strcpy(dumpFile, argv[1]);
- tclMemDumpFileName = dumpFile;
- quitFlag = 1;
- return TCL_OK;
-}
-#endif