os/persistentdata/persistentstorage/sqlite3api/TEST/TCL/tcldistribution/generic/tclCkalloc.c
First public contribution.
4 * Interface to malloc and free that provides support for debugging problems
5 * involving overwritten, double freeing memory and loss of memory.
7 * Copyright (c) 1991-1994 The Regents of the University of California.
8 * Copyright (c) 1994-1997 Sun Microsystems, Inc.
9 * Copyright (c) 1998-1999 by Scriptics Corporation.
10 * Portions Copyright (c) 2007-2008 Nokia Corporation and/or its subsidiaries. All rights reserved.
12 * See the file "license.terms" for information on usage and redistribution
13 * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
15 * This code contributed by Karl Lehenbauer and Mark Diekhans
17 * RCS: @(#) $Id: tclCkalloc.c,v 1.19 2003/01/19 07:21:18 hobbs Exp $
29 * One of the following structures is allocated each time the
30 * "memory tag" command is invoked, to hold the current tag.
33 typedef struct MemTag {
34 int refCount; /* Number of mem_headers referencing
36 char string[4]; /* Actual size of string will be as
37 * large as needed for actual tag. This
38 * must be the last field in the structure. */
41 #define TAG_SIZE(bytesInString) ((unsigned) sizeof(MemTag) + bytesInString - 3)
43 static MemTag *curTagPtr = NULL;/* Tag to use in all future mem_headers
44 * (set by "memory tag" command). */
47 * One of the following structures is allocated just before each
48 * dynamically allocated chunk of memory, both to record information
49 * about the chunk and to help detect chunk under-runs.
52 #define LOW_GUARD_SIZE (8 + (32 - (sizeof(long) + sizeof(int)))%8)
54 struct mem_header *flink;
55 struct mem_header *blink;
56 MemTag *tagPtr; /* Tag from "memory tag" command; may be
61 unsigned char low_guard[LOW_GUARD_SIZE];
62 /* Aligns body on 8-byte boundary, plus
63 * provides at least 8 additional guard bytes
64 * to detect underruns. */
65 char body[1]; /* First byte of client's space. Actual
66 * size of this field will be larger than
70 #if !defined(__SYMBIAN32__) || !defined(__WINSCW__)
71 static struct mem_header *allocHead = NULL; /* List of allocated structures */
73 typedef struct mem_header (*memHeaderPtr);
74 #define allocHead (*(memHeaderPtr*)get_allocHead())
77 #define GUARD_VALUE 0141
80 * The following macro determines the amount of guard space *above* each
84 #define HIGH_GUARD_SIZE 8
87 * The following macro computes the offset of the "body" field within
88 * mem_header. It is used to get back to the header pointer from the
89 * body pointer that's used by clients.
93 ((unsigned long) (&((struct mem_header *) 0)->body))
95 static int total_mallocs = 0;
96 static int total_frees = 0;
97 static int current_bytes_malloced = 0;
98 static int maximum_bytes_malloced = 0;
99 static int current_malloc_packets = 0;
100 static int maximum_malloc_packets = 0;
101 static int break_on_malloc = 0;
102 static int trace_on_at_malloc = 0;
103 static int alloc_tracing = FALSE;
104 static int init_malloced_bodies = TRUE;
106 static int validate_memory = TRUE;
108 static int validate_memory = FALSE;
112 * The following variable indicates to TclFinalizeMemorySubsystem()
113 * that it should dump out the state of memory before exiting. If the
114 * value is non-NULL, it gives the name of the file in which to
115 * dump memory usage information.
118 char *tclMemDumpFileName = NULL;
120 static char *onExitMemDumpFileName = NULL;
121 static char dumpFile[100]; /* Records where to dump memory allocation
125 * Mutex to serialize allocations. This is a low-level mutex that must
126 * be explicitly initialized. This is necessary because the self
127 * initializing mutexes use ckalloc...
129 static Tcl_Mutex *ckallocMutexPtr;
130 static int ckallocInit = 0;
133 * Prototypes for procedures defined in this file:
136 static int CheckmemCmd _ANSI_ARGS_((ClientData clientData,
137 Tcl_Interp *interp, int argc, CONST char *argv[]));
138 static int MemoryCmd _ANSI_ARGS_((ClientData clientData,
139 Tcl_Interp *interp, int argc, CONST char **argv));
140 static void ValidateMemory _ANSI_ARGS_((
141 struct mem_header *memHeaderP, CONST char *file,
142 int line, int nukeGuards));
145 *----------------------------------------------------------------------
147 * TclInitDbCkalloc --
148 * Initialize the locks used by the allocator.
149 * This is only appropriate to call in a single threaded environment,
150 * such as during TclInitSubsystems.
152 *----------------------------------------------------------------------
159 ckallocMutexPtr = Tcl_GetAllocMutex();
164 *----------------------------------------------------------------------
166 * TclDumpMemoryInfo --
167 * Display the global memory management statistics.
169 *----------------------------------------------------------------------
172 TclDumpMemoryInfo(outFile)
175 fprintf(outFile,"total mallocs %10d\n",
177 fprintf(outFile,"total frees %10d\n",
179 fprintf(outFile,"current packets allocated %10d\n",
180 current_malloc_packets);
181 fprintf(outFile,"current bytes allocated %10d\n",
182 current_bytes_malloced);
183 fprintf(outFile,"maximum packets allocated %10d\n",
184 maximum_malloc_packets);
185 fprintf(outFile,"maximum bytes allocated %10d\n",
186 maximum_bytes_malloced);
191 *----------------------------------------------------------------------
195 * Validate memory guard zones for a particular chunk of allocated
202 * Prints validation information about the allocated memory to stderr.
204 *----------------------------------------------------------------------
208 ValidateMemory(memHeaderP, file, line, nukeGuards)
209 struct mem_header *memHeaderP; /* Memory chunk to validate */
210 CONST char *file; /* File containing the call to
211 * Tcl_ValidateAllMemory */
212 int line; /* Line number of call to
213 * Tcl_ValidateAllMemory */
214 int nukeGuards; /* If non-zero, indicates that the
215 * memory guards are to be reset to 0
216 * after they have been printed */
218 unsigned char *hiPtr;
220 int guard_failed = FALSE;
223 for (idx = 0; idx < LOW_GUARD_SIZE; idx++) {
224 byte = *(memHeaderP->low_guard + idx);
225 if (byte != GUARD_VALUE) {
229 fprintf(stderr, "low guard byte %d is 0x%x \t%c\n", idx, byte,
230 (isprint(UCHAR(byte)) ? byte : ' ')); /* INTL: bytes */
234 TclDumpMemoryInfo (stderr);
235 fprintf(stderr, "low guard failed at %lx, %s %d\n",
236 (long unsigned int) memHeaderP->body, file, line);
237 fflush(stderr); /* In case name pointer is bad. */
238 fprintf(stderr, "%ld bytes allocated at (%s %d)\n", memHeaderP->length,
239 memHeaderP->file, memHeaderP->line);
240 panic ("Memory validation failure");
243 hiPtr = (unsigned char *)memHeaderP->body + memHeaderP->length;
244 for (idx = 0; idx < HIGH_GUARD_SIZE; idx++) {
245 byte = *(hiPtr + idx);
246 if (byte != GUARD_VALUE) {
250 fprintf(stderr, "hi guard byte %d is 0x%x \t%c\n", idx, byte,
251 (isprint(UCHAR(byte)) ? byte : ' ')); /* INTL: bytes */
256 TclDumpMemoryInfo (stderr);
257 fprintf(stderr, "high guard failed at %lx, %s %d\n",
258 (long unsigned int) memHeaderP->body, file, line);
259 fflush(stderr); /* In case name pointer is bad. */
260 fprintf(stderr, "%ld bytes allocated at (%s %d)\n",
261 memHeaderP->length, memHeaderP->file,
263 panic("Memory validation failure");
267 memset ((char *) memHeaderP->low_guard, 0, LOW_GUARD_SIZE);
268 memset ((char *) hiPtr, 0, HIGH_GUARD_SIZE);
274 *----------------------------------------------------------------------
276 * Tcl_ValidateAllMemory --
278 * Validate memory guard regions for all allocated memory.
284 * Displays memory validation information to stderr.
286 *----------------------------------------------------------------------
289 Tcl_ValidateAllMemory (file, line)
290 CONST char *file; /* File from which Tcl_ValidateAllMemory was called */
291 int line; /* Line number of call to Tcl_ValidateAllMemory */
293 struct mem_header *memScanP;
298 Tcl_MutexLock(ckallocMutexPtr);
299 for (memScanP = allocHead; memScanP != NULL; memScanP = memScanP->flink) {
300 ValidateMemory(memScanP, file, line, FALSE);
302 Tcl_MutexUnlock(ckallocMutexPtr);
306 *----------------------------------------------------------------------
308 * Tcl_DumpActiveMemory --
310 * Displays all allocated memory to a file; if no filename is given,
311 * information will be written to stderr.
314 * Return TCL_ERROR if an error accessing the file occurs, `errno'
315 * will have the file error number left in it.
316 *----------------------------------------------------------------------
319 Tcl_DumpActiveMemory (fileName)
320 CONST char *fileName; /* Name of the file to write info to */
323 struct mem_header *memScanP;
326 if (fileName == NULL) {
329 fileP = fopen(fileName, "w");
335 Tcl_MutexLock(ckallocMutexPtr);
336 for (memScanP = allocHead; memScanP != NULL; memScanP = memScanP->flink) {
337 address = &memScanP->body [0];
338 fprintf(fileP, "%8lx - %8lx %7ld @ %s %d %s",
339 (long unsigned int) address,
340 (long unsigned int) address + memScanP->length - 1,
341 memScanP->length, memScanP->file, memScanP->line,
342 (memScanP->tagPtr == NULL) ? "" : memScanP->tagPtr->string);
343 (void) fputc('\n', fileP);
345 Tcl_MutexUnlock(ckallocMutexPtr);
347 if (fileP != stderr) {
354 *----------------------------------------------------------------------
356 * Tcl_DbCkalloc - debugging ckalloc
358 * Allocate the requested amount of space plus some extra for
359 * guard bands at both ends of the request, plus a size, panicing
360 * if there isn't enough space, then write in the guard bands
361 * and return the address of the space in the middle that the
364 * The second and third arguments are file and line, these contain
365 * the filename and line number corresponding to the caller.
366 * These are sent by the ckalloc macro; it uses the preprocessor
367 * autodefines __FILE__ and __LINE__.
369 *----------------------------------------------------------------------
372 Tcl_DbCkalloc(size, file, line)
377 struct mem_header *result;
380 Tcl_ValidateAllMemory (file, line);
382 result = (struct mem_header *) TclpAlloc((unsigned)size +
383 sizeof(struct mem_header) + HIGH_GUARD_SIZE);
384 if (result == NULL) {
386 TclDumpMemoryInfo(stderr);
387 panic("unable to alloc %u bytes, %s line %d", size, file, line);
391 * Fill in guard zones and size. Also initialize the contents of
392 * the block with bogus bytes to detect uses of initialized data.
393 * Link into allocated list.
395 if (init_malloced_bodies) {
396 memset ((VOID *) result, GUARD_VALUE,
397 size + sizeof(struct mem_header) + HIGH_GUARD_SIZE);
399 memset ((char *) result->low_guard, GUARD_VALUE, LOW_GUARD_SIZE);
400 memset (result->body + size, GUARD_VALUE, HIGH_GUARD_SIZE);
405 Tcl_MutexLock(ckallocMutexPtr);
406 result->length = size;
407 result->tagPtr = curTagPtr;
408 if (curTagPtr != NULL) {
409 curTagPtr->refCount++;
413 result->flink = allocHead;
414 result->blink = NULL;
416 if (allocHead != NULL)
417 allocHead->blink = result;
421 if (trace_on_at_malloc && (total_mallocs >= trace_on_at_malloc)) {
422 (void) fflush(stdout);
423 fprintf(stderr, "reached malloc trace enable point (%d)\n",
426 alloc_tracing = TRUE;
427 trace_on_at_malloc = 0;
431 fprintf(stderr,"ckalloc %lx %u %s %d\n",
432 (long unsigned int) result->body, size, file, line);
434 if (break_on_malloc && (total_mallocs >= break_on_malloc)) {
436 (void) fflush(stdout);
437 fprintf(stderr,"reached malloc break limit (%d)\n",
439 fprintf(stderr, "program will now enter C debugger\n");
440 (void) fflush(stderr);
444 current_malloc_packets++;
445 if (current_malloc_packets > maximum_malloc_packets)
446 maximum_malloc_packets = current_malloc_packets;
447 current_bytes_malloced += size;
448 if (current_bytes_malloced > maximum_bytes_malloced)
449 maximum_bytes_malloced = current_bytes_malloced;
451 Tcl_MutexUnlock(ckallocMutexPtr);
457 Tcl_AttemptDbCkalloc(size, file, line)
462 struct mem_header *result;
465 Tcl_ValidateAllMemory (file, line);
467 result = (struct mem_header *) TclpAlloc((unsigned)size +
468 sizeof(struct mem_header) + HIGH_GUARD_SIZE);
469 if (result == NULL) {
471 TclDumpMemoryInfo(stderr);
476 * Fill in guard zones and size. Also initialize the contents of
477 * the block with bogus bytes to detect uses of initialized data.
478 * Link into allocated list.
480 if (init_malloced_bodies) {
481 memset ((VOID *) result, GUARD_VALUE,
482 size + sizeof(struct mem_header) + HIGH_GUARD_SIZE);
484 memset ((char *) result->low_guard, GUARD_VALUE, LOW_GUARD_SIZE);
485 memset (result->body + size, GUARD_VALUE, HIGH_GUARD_SIZE);
490 Tcl_MutexLock(ckallocMutexPtr);
491 result->length = size;
492 result->tagPtr = curTagPtr;
493 if (curTagPtr != NULL) {
494 curTagPtr->refCount++;
498 result->flink = allocHead;
499 result->blink = NULL;
501 if (allocHead != NULL)
502 allocHead->blink = result;
506 if (trace_on_at_malloc && (total_mallocs >= trace_on_at_malloc)) {
507 (void) fflush(stdout);
508 fprintf(stderr, "reached malloc trace enable point (%d)\n",
511 alloc_tracing = TRUE;
512 trace_on_at_malloc = 0;
516 fprintf(stderr,"ckalloc %lx %u %s %d\n",
517 (long unsigned int) result->body, size, file, line);
519 if (break_on_malloc && (total_mallocs >= break_on_malloc)) {
521 (void) fflush(stdout);
522 fprintf(stderr,"reached malloc break limit (%d)\n",
524 fprintf(stderr, "program will now enter C debugger\n");
525 (void) fflush(stderr);
529 current_malloc_packets++;
530 if (current_malloc_packets > maximum_malloc_packets)
531 maximum_malloc_packets = current_malloc_packets;
532 current_bytes_malloced += size;
533 if (current_bytes_malloced > maximum_bytes_malloced)
534 maximum_bytes_malloced = current_bytes_malloced;
536 Tcl_MutexUnlock(ckallocMutexPtr);
543 *----------------------------------------------------------------------
545 * Tcl_DbCkfree - debugging ckfree
547 * Verify that the low and high guards are intact, and if so
548 * then free the buffer else panic.
550 * The guards are erased after being checked to catch duplicate
553 * The second and third arguments are file and line, these contain
554 * the filename and line number corresponding to the caller.
555 * These are sent by the ckfree macro; it uses the preprocessor
556 * autodefines __FILE__ and __LINE__.
558 *----------------------------------------------------------------------
562 Tcl_DbCkfree(ptr, file, line)
567 struct mem_header *memp;
574 * The following cast is *very* tricky. Must convert the pointer
575 * to an integer before doing arithmetic on it, because otherwise
576 * the arithmetic will be done differently (and incorrectly) on
577 * word-addressed machines such as Crays (will subtract only bytes,
578 * even though BODY_OFFSET is in words on these machines).
581 memp = (struct mem_header *) (((unsigned long) ptr) - BODY_OFFSET);
584 fprintf(stderr, "ckfree %lx %ld %s %d\n",
585 (long unsigned int) memp->body, memp->length, file, line);
588 if (validate_memory) {
589 Tcl_ValidateAllMemory(file, line);
592 Tcl_MutexLock(ckallocMutexPtr);
593 ValidateMemory(memp, file, line, TRUE);
594 if (init_malloced_bodies) {
595 memset((VOID *) ptr, GUARD_VALUE, (size_t) memp->length);
599 current_malloc_packets--;
600 current_bytes_malloced -= memp->length;
602 if (memp->tagPtr != NULL) {
603 memp->tagPtr->refCount--;
604 if ((memp->tagPtr->refCount == 0) && (curTagPtr != memp->tagPtr)) {
605 TclpFree((char *) memp->tagPtr);
610 * Delink from allocated list
612 if (memp->flink != NULL)
613 memp->flink->blink = memp->blink;
614 if (memp->blink != NULL)
615 memp->blink->flink = memp->flink;
616 if (allocHead == memp)
617 allocHead = memp->flink;
618 TclpFree((char *) memp);
619 Tcl_MutexUnlock(ckallocMutexPtr);
625 *--------------------------------------------------------------------
627 * Tcl_DbCkrealloc - debugging ckrealloc
629 * Reallocate a chunk of memory by allocating a new one of the
630 * right size, copying the old data to the new location, and then
631 * freeing the old memory space, using all the memory checking
632 * features of this package.
634 *--------------------------------------------------------------------
637 Tcl_DbCkrealloc(ptr, size, file, line)
644 unsigned int copySize;
645 struct mem_header *memp;
648 return Tcl_DbCkalloc(size, file, line);
652 * See comment from Tcl_DbCkfree before you change the following
656 memp = (struct mem_header *) (((unsigned long) ptr) - BODY_OFFSET);
659 if (copySize > (unsigned int) memp->length) {
660 copySize = memp->length;
662 new = Tcl_DbCkalloc(size, file, line);
663 memcpy((VOID *) new, (VOID *) ptr, (size_t) copySize);
664 Tcl_DbCkfree(ptr, file, line);
669 Tcl_AttemptDbCkrealloc(ptr, size, file, line)
676 unsigned int copySize;
677 struct mem_header *memp;
680 return Tcl_AttemptDbCkalloc(size, file, line);
684 * See comment from Tcl_DbCkfree before you change the following
688 memp = (struct mem_header *) (((unsigned long) ptr) - BODY_OFFSET);
691 if (copySize > (unsigned int) memp->length) {
692 copySize = memp->length;
694 new = Tcl_AttemptDbCkalloc(size, file, line);
698 memcpy((VOID *) new, (VOID *) ptr, (size_t) copySize);
699 Tcl_DbCkfree(ptr, file, line);
705 *----------------------------------------------------------------------
707 * Tcl_Alloc, et al. --
709 * These functions are defined in terms of the debugging versions
710 * when TCL_MEM_DEBUG is set.
713 * Same as the debug versions.
716 * Same as the debug versions.
718 *----------------------------------------------------------------------
724 #undef Tcl_AttemptAlloc
725 #undef Tcl_AttemptRealloc
731 return Tcl_DbCkalloc(size, "unknown", 0);
735 Tcl_AttemptAlloc(size)
738 return Tcl_AttemptDbCkalloc(size, "unknown", 0);
745 Tcl_DbCkfree(ptr, "unknown", 0);
749 Tcl_Realloc(ptr, size)
753 return Tcl_DbCkrealloc(ptr, size, "unknown", 0);
756 Tcl_AttemptRealloc(ptr, size)
760 return Tcl_AttemptDbCkrealloc(ptr, size, "unknown", 0);
764 *----------------------------------------------------------------------
767 * Implements the Tcl "memory" command, which provides Tcl-level
768 * control of Tcl memory debugging information.
769 * memory active $file
770 * memory break_on_malloc $count
773 * memory onexit $file
775 * memory trace on|off
776 * memory trace_on_at_malloc $count
777 * memory validate on|off
780 * Standard TCL results.
782 *----------------------------------------------------------------------
786 MemoryCmd (clientData, interp, argc, argv)
787 ClientData clientData;
792 CONST char *fileName;
797 Tcl_AppendResult(interp, "wrong # args: should be \"",
798 argv[0], " option [args..]\"", (char *) NULL);
802 if ((strcmp(argv[1],"active") == 0) || (strcmp(argv[1],"display") == 0)) {
804 Tcl_AppendResult(interp, "wrong # args: should be \"",
805 argv[0], " ", argv[1], " file\"", (char *) NULL);
808 fileName = Tcl_TranslateFileName(interp, argv[2], &buffer);
809 if (fileName == NULL) {
812 result = Tcl_DumpActiveMemory (fileName);
813 Tcl_DStringFree(&buffer);
814 if (result != TCL_OK) {
815 Tcl_AppendResult(interp, "error accessing ", argv[2],
821 if (strcmp(argv[1],"break_on_malloc") == 0) {
825 if (Tcl_GetInt(interp, argv[2], &break_on_malloc) != TCL_OK) {
830 if (strcmp(argv[1],"info") == 0) {
832 sprintf(buf, "%-25s %10d\n%-25s %10d\n%-25s %10d\n%-25s %10d\n%-25s %10d\n%-25s %10d\n",
833 "total mallocs", total_mallocs, "total frees", total_frees,
834 "current packets allocated", current_malloc_packets,
835 "current bytes allocated", current_bytes_malloced,
836 "maximum packets allocated", maximum_malloc_packets,
837 "maximum bytes allocated", maximum_bytes_malloced);
838 Tcl_SetResult(interp, buf, TCL_VOLATILE);
841 if (strcmp(argv[1],"init") == 0) {
845 init_malloced_bodies = (strcmp(argv[2],"on") == 0);
848 if (strcmp(argv[1],"onexit") == 0) {
850 Tcl_AppendResult(interp, "wrong # args: should be \"",
851 argv[0], " onexit file\"", (char *) NULL);
854 fileName = Tcl_TranslateFileName(interp, argv[2], &buffer);
855 if (fileName == NULL) {
858 onExitMemDumpFileName = dumpFile;
859 strcpy(onExitMemDumpFileName,fileName);
860 Tcl_DStringFree(&buffer);
863 if (strcmp(argv[1],"tag") == 0) {
865 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
866 " tag string\"", (char *) NULL);
869 if ((curTagPtr != NULL) && (curTagPtr->refCount == 0)) {
870 TclpFree((char *) curTagPtr);
872 curTagPtr = (MemTag *) TclpAlloc(TAG_SIZE(strlen(argv[2])));
873 curTagPtr->refCount = 0;
874 strcpy(curTagPtr->string, argv[2]);
877 if (strcmp(argv[1],"trace") == 0) {
881 alloc_tracing = (strcmp(argv[2],"on") == 0);
885 if (strcmp(argv[1],"trace_on_at_malloc") == 0) {
889 if (Tcl_GetInt(interp, argv[2], &trace_on_at_malloc) != TCL_OK) {
894 if (strcmp(argv[1],"validate") == 0) {
898 validate_memory = (strcmp(argv[2],"on") == 0);
902 Tcl_AppendResult(interp, "bad option \"", argv[1],
903 "\": should be active, break_on_malloc, info, init, onexit, ",
904 "tag, trace, trace_on_at_malloc, or validate", (char *) NULL);
908 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
909 " ", argv[1], " count\"", (char *) NULL);
913 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
914 " ", argv[1], " on|off\"", (char *) NULL);
919 *----------------------------------------------------------------------
923 * This is the command procedure for the "checkmem" command, which
924 * causes the application to exit after printing information about
925 * memory usage to the file passed to this command as its first
929 * Returns a standard Tcl completion code.
934 *----------------------------------------------------------------------
938 CheckmemCmd(clientData, interp, argc, argv)
939 ClientData clientData; /* Not used. */
940 Tcl_Interp *interp; /* Interpreter for evaluation. */
941 int argc; /* Number of arguments. */
942 CONST char *argv[]; /* String values of arguments. */
945 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
946 " fileName\"", (char *) NULL);
949 tclMemDumpFileName = dumpFile;
950 strcpy(tclMemDumpFileName, argv[1]);
955 *----------------------------------------------------------------------
959 * Create the "memory" and "checkmem" commands in the given
966 * New commands are added to the interpreter.
968 *----------------------------------------------------------------------
972 Tcl_InitMemory(interp)
973 Tcl_Interp *interp; /* Interpreter in which commands should be added */
976 Tcl_CreateCommand (interp, "memory", MemoryCmd, (ClientData) NULL,
977 (Tcl_CmdDeleteProc *) NULL);
978 Tcl_CreateCommand(interp, "checkmem", CheckmemCmd, (ClientData) 0,
979 (Tcl_CmdDeleteProc *) NULL);
983 #else /* TCL_MEM_DEBUG */
985 /* This is the !TCL_MEM_DEBUG case */
987 #undef Tcl_InitMemory
988 #undef Tcl_DumpActiveMemory
989 #undef Tcl_ValidateAllMemory
993 *----------------------------------------------------------------------
996 * Interface to TclpAlloc when TCL_MEM_DEBUG is disabled. It does check
997 * that memory was actually allocated.
999 *----------------------------------------------------------------------
1008 result = TclpAlloc(size);
1010 * Most systems will not alloc(0), instead bumping it to one so
1011 * that NULL isn't returned. Some systems (AIX, Tru64) will alloc(0)
1012 * by returning NULL, so we have to check that the NULL we get is
1013 * not in response to alloc(0).
1015 * The ANSI spec actually says that systems either return NULL *or*
1016 * a special pointer on failure, but we only check for NULL
1018 if ((result == NULL) && size) {
1019 panic("unable to alloc %u bytes", size);
1025 Tcl_DbCkalloc(size, file, line)
1032 result = (char *) TclpAlloc(size);
1034 if ((result == NULL) && size) {
1036 panic("unable to alloc %u bytes, %s line %d", size, file, line);
1042 *----------------------------------------------------------------------
1044 * Tcl_AttemptAlloc --
1045 * Interface to TclpAlloc when TCL_MEM_DEBUG is disabled. It does not
1046 * check that memory was actually allocated.
1048 *----------------------------------------------------------------------
1052 Tcl_AttemptAlloc (size)
1057 result = TclpAlloc(size);
1062 Tcl_AttemptDbCkalloc(size, file, line)
1069 result = (char *) TclpAlloc(size);
1075 *----------------------------------------------------------------------
1078 * Interface to TclpRealloc when TCL_MEM_DEBUG is disabled. It does
1079 * check that memory was actually allocated.
1081 *----------------------------------------------------------------------
1085 Tcl_Realloc(ptr, size)
1091 result = TclpRealloc(ptr, size);
1093 if ((result == NULL) && size) {
1094 panic("unable to realloc %u bytes", size);
1100 Tcl_DbCkrealloc(ptr, size, file, line)
1108 result = (char *) TclpRealloc(ptr, size);
1110 if ((result == NULL) && size) {
1112 panic("unable to realloc %u bytes, %s line %d", size, file, line);
1118 *----------------------------------------------------------------------
1120 * Tcl_AttemptRealloc --
1121 * Interface to TclpRealloc when TCL_MEM_DEBUG is disabled. It does
1122 * not check that memory was actually allocated.
1124 *----------------------------------------------------------------------
1128 Tcl_AttemptRealloc(ptr, size)
1134 result = TclpRealloc(ptr, size);
1139 Tcl_AttemptDbCkrealloc(ptr, size, file, line)
1147 result = (char *) TclpRealloc(ptr, size);
1152 *----------------------------------------------------------------------
1155 * Interface to TclpFree when TCL_MEM_DEBUG is disabled. Done here
1156 * rather in the macro to keep some modules from being compiled with
1157 * TCL_MEM_DEBUG enabled and some with it disabled.
1159 *----------------------------------------------------------------------
1170 Tcl_DbCkfree(ptr, file, line)
1180 *----------------------------------------------------------------------
1183 * Dummy initialization for memory command, which is only available
1184 * if TCL_MEM_DEBUG is on.
1186 *----------------------------------------------------------------------
1190 Tcl_InitMemory(interp)
1196 Tcl_DumpActiveMemory(fileName)
1197 CONST char *fileName;
1203 Tcl_ValidateAllMemory(file, line)
1210 TclDumpMemoryInfo(outFile)
1215 #endif /* TCL_MEM_DEBUG */
1218 *---------------------------------------------------------------------------
1220 * TclFinalizeMemorySubsystem --
1222 * This procedure is called to finalize all the structures that
1223 * are used by the memory allocator on a per-process basis.
1229 * This subsystem is self-initializing, since memory can be
1230 * allocated before Tcl is formally initialized. After this call,
1231 * this subsystem has been reset to its initial state and is
1234 *---------------------------------------------------------------------------
1238 TclFinalizeMemorySubsystem()
1240 #ifdef TCL_MEM_DEBUG
1241 if (tclMemDumpFileName != NULL) {
1242 Tcl_DumpActiveMemory(tclMemDumpFileName);
1243 } else if (onExitMemDumpFileName != NULL) {
1244 Tcl_DumpActiveMemory(onExitMemDumpFileName);
1246 Tcl_MutexLock(ckallocMutexPtr);
1247 if (curTagPtr != NULL) {
1248 TclpFree((char *) curTagPtr);
1252 Tcl_MutexUnlock(ckallocMutexPtr);
1256 TclFinalizeAllocSubsystem();