Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Overview
Comment: | Add some more logging to the malloc system used when SQLITE_MEMDEBUG is defined. (CVS 4901) |
---|---|
Downloads: | Tarball | ZIP archive |
Timelines: | family | ancestors | descendants | both | trunk |
Files: | files | file ages | folders |
SHA1: |
79738f582fbac87f2d335e0c6b7f53e3 |
User & Date: | danielk1977 2008-03-21 14:22:44.000 |
Context
2008-03-21
| ||
16:45 | Add a completely new testing system for the Bitvec object. The new testing system uses sqlite3_test_control() instead of unpublished APIs. Now provides 100% condition/decision coverage. Obscure bugs in Bitvec found and fixed as a result of the enhanced coverage. (CVS 4902) (check-in: 2498d3ea36 user: drh tags: trunk) | |
14:22 | Add some more logging to the malloc system used when SQLITE_MEMDEBUG is defined. (CVS 4901) (check-in: 79738f582f user: danielk1977 tags: trunk) | |
2008-03-20
| ||
18:00 | In the sqlite3_limit() interface, take out the feature where zero means use the hard upper bound. If an application wants the hard upper bound, it can set the limit to 0x7fffffff and the bound will be automatically truncated. (CVS 4900) (check-in: d6be1f495e user: drh tags: trunk) | |
Changes
Changes to src/mem2.c.
︙ | ︙ | |||
8 9 10 11 12 13 14 | ** May you find forgiveness for yourself and forgive others. ** May you share freely, never taking more than you give. ** ************************************************************************* ** This file contains the C functions that implement a memory ** allocation subsystem for use by SQLite. ** | | | 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | ** May you find forgiveness for yourself and forgive others. ** May you share freely, never taking more than you give. ** ************************************************************************* ** This file contains the C functions that implement a memory ** allocation subsystem for use by SQLite. ** ** $Id: mem2.c,v 1.23 2008/03/21 14:22:44 danielk1977 Exp $ */ #include "sqliteInt.h" /* ** This version of the memory allocator is used only if the ** SQLITE_MEMDEBUG macro is defined */ |
︙ | ︙ | |||
103 104 105 106 107 108 109 110 111 112 113 114 115 116 | struct MemBlockHdr *pFirst; struct MemBlockHdr *pLast; /* ** The number of levels of backtrace to save in new allocations. */ int nBacktrace; /* ** Title text to insert in front of each block */ int nTitle; /* Bytes of zTitle to save. Includes '\0' and padding */ char zTitle[100]; /* The title text */ | > | 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 | struct MemBlockHdr *pFirst; struct MemBlockHdr *pLast; /* ** The number of levels of backtrace to save in new allocations. */ int nBacktrace; void (*xBacktrace)(int, int, void **); /* ** Title text to insert in front of each block */ int nTitle; /* Bytes of zTitle to save. Includes '\0' and padding */ char zTitle[100]; /* The title text */ |
︙ | ︙ | |||
282 283 284 285 286 287 288 289 290 291 292 293 294 295 | pHdr->iForeGuard = FOREGUARD; pHdr->nBacktraceSlots = mem.nBacktrace; pHdr->nTitle = mem.nTitle; if( mem.nBacktrace ){ void *aAddr[40]; pHdr->nBacktrace = backtrace(aAddr, mem.nBacktrace+1)-1; memcpy(pBt, &aAddr[1], pHdr->nBacktrace*sizeof(void*)); }else{ pHdr->nBacktrace = 0; } if( mem.nTitle ){ memcpy(z, mem.zTitle, mem.nTitle); } pHdr->iSize = nByte; | > > > | 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 | pHdr->iForeGuard = FOREGUARD; pHdr->nBacktraceSlots = mem.nBacktrace; pHdr->nTitle = mem.nTitle; if( mem.nBacktrace ){ void *aAddr[40]; pHdr->nBacktrace = backtrace(aAddr, mem.nBacktrace+1)-1; memcpy(pBt, &aAddr[1], pHdr->nBacktrace*sizeof(void*)); if( mem.xBacktrace ){ mem.xBacktrace(nByte, pHdr->nBacktrace-1, &aAddr[1]); } }else{ pHdr->nBacktrace = 0; } if( mem.nTitle ){ memcpy(z, mem.zTitle, mem.nTitle); } pHdr->iSize = nByte; |
︙ | ︙ | |||
384 385 386 387 388 389 390 391 392 393 394 395 396 397 | */ void sqlite3MemdebugBacktrace(int depth){ if( depth<0 ){ depth = 0; } if( depth>20 ){ depth = 20; } depth = (depth+1)&0xfe; mem.nBacktrace = depth; } /* ** Set the title string for subsequent allocations. */ void sqlite3MemdebugSettitle(const char *zTitle){ int n = strlen(zTitle) + 1; enterMem(); | > > > > | 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 | */ void sqlite3MemdebugBacktrace(int depth){ if( depth<0 ){ depth = 0; } if( depth>20 ){ depth = 20; } depth = (depth+1)&0xfe; mem.nBacktrace = depth; } void sqlite3MemdebugBacktraceCallback(void (*xBacktrace)(int, int, void **)){ mem.xBacktrace = xBacktrace; } /* ** Set the title string for subsequent allocations. */ void sqlite3MemdebugSettitle(const char *zTitle){ int n = strlen(zTitle) + 1; enterMem(); |
︙ | ︙ |
Changes to src/test_malloc.c.
︙ | ︙ | |||
9 10 11 12 13 14 15 | ** May you share freely, never taking more than you give. ** ************************************************************************* ** ** This file contains code used to implement test interfaces to the ** memory allocation subsystem. ** | | | 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | ** May you share freely, never taking more than you give. ** ************************************************************************* ** ** This file contains code used to implement test interfaces to the ** memory allocation subsystem. ** ** $Id: test_malloc.c,v 1.18 2008/03/21 14:22:44 danielk1977 Exp $ */ #include "sqliteInt.h" #include "tcl.h" #include <stdlib.h> #include <string.h> #include <assert.h> |
︙ | ︙ | |||
503 504 505 506 507 508 509 510 511 512 513 514 515 516 | extern int sqlite3MemdebugSettitle(const char*); sqlite3MemdebugSettitle(zTitle); } #endif return TCL_OK; } /* ** Register commands with the TCL interpreter. */ int Sqlitetest_malloc_Init(Tcl_Interp *interp){ static struct { char *zName; | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 | extern int sqlite3MemdebugSettitle(const char*); sqlite3MemdebugSettitle(zTitle); } #endif return TCL_OK; } #define MALLOC_LOG_FRAMES 5 static Tcl_HashTable aMallocLog; static int mallocLogEnabled = 0; typedef struct MallocLog MallocLog; struct MallocLog { int nCall; int nByte; }; static void test_memdebug_callback(int nByte, int nFrame, void **aFrame){ if( mallocLogEnabled ){ MallocLog *pLog; Tcl_HashEntry *pEntry; int isNew; int aKey[MALLOC_LOG_FRAMES]; int nKey = sizeof(int)*MALLOC_LOG_FRAMES; memset(aKey, 0, nKey); if( (sizeof(void*)*nFrame)<nKey ){ nKey = nFrame*sizeof(void*); } memcpy(aKey, aFrame, nKey); pEntry = Tcl_CreateHashEntry(&aMallocLog, (const char *)aKey, &isNew); if( isNew ){ pLog = (MallocLog *)Tcl_Alloc(sizeof(MallocLog)); memset(pLog, 0, sizeof(MallocLog)); Tcl_SetHashValue(pEntry, (ClientData)pLog); }else{ pLog = (MallocLog *)Tcl_GetHashValue(pEntry); } pLog->nCall++; pLog->nByte += nByte; } } static int test_memdebug_log( void * clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[] ){ static int isInit = 0; int iSub; enum MB_enum { MB_LOG_START, MB_LOG_STOP, MB_LOG_DUMP, MB_LOG_CLEAR }; static const char *MB_strs[] = { "start", "stop", "dump", "clear" }; if( !isInit ){ #ifdef SQLITE_MEMDEBUG extern void sqlite3MemdebugBacktraceCallback( void (*xBacktrace)(int, int, void **)); sqlite3MemdebugBacktraceCallback(test_memdebug_callback); #endif Tcl_InitHashTable(&aMallocLog, MALLOC_LOG_FRAMES); isInit = 1; } if( objc<2 ){ Tcl_WrongNumArgs(interp, 1, objv, "SUB-COMMAND ..."); } if( Tcl_GetIndexFromObj(interp, objv[1], MB_strs, "sub-command", 0, &iSub) ){ return TCL_ERROR; } switch( (enum MB_enum)iSub ){ case MB_LOG_START: mallocLogEnabled = 1; break; case MB_LOG_STOP: mallocLogEnabled = 0; break; case MB_LOG_DUMP: { Tcl_HashSearch search; Tcl_HashEntry *pEntry; Tcl_Obj *pRet = Tcl_NewObj(); assert(sizeof(int)==sizeof(void*)); for( pEntry=Tcl_FirstHashEntry(&aMallocLog, &search); pEntry; pEntry=Tcl_NextHashEntry(&search) ){ Tcl_Obj *apElem[MALLOC_LOG_FRAMES+2]; MallocLog *pLog = (MallocLog *)Tcl_GetHashValue(pEntry); int *aKey = (int *)Tcl_GetHashKey(&aMallocLog, pEntry); int ii; apElem[0] = Tcl_NewIntObj(pLog->nCall); apElem[1] = Tcl_NewIntObj(pLog->nByte); for(ii=0; ii<MALLOC_LOG_FRAMES; ii++){ apElem[ii+2] = Tcl_NewIntObj(aKey[ii]); } Tcl_ListObjAppendElement(interp, pRet, Tcl_NewListObj(MALLOC_LOG_FRAMES+2, apElem) ); } Tcl_SetObjResult(interp, pRet); break; } case MB_LOG_CLEAR: { Tcl_HashSearch search; Tcl_HashEntry *pEntry; for( pEntry=Tcl_FirstHashEntry(&aMallocLog, &search); pEntry; pEntry=Tcl_NextHashEntry(&search) ){ MallocLog *pLog = (MallocLog *)Tcl_GetHashValue(pEntry); Tcl_Free((char *)pLog); } Tcl_DeleteHashTable(&aMallocLog); Tcl_InitHashTable(&aMallocLog, MALLOC_LOG_FRAMES); } } return TCL_OK; } /* ** Register commands with the TCL interpreter. */ int Sqlitetest_malloc_Init(Tcl_Interp *interp){ static struct { char *zName; |
︙ | ︙ | |||
525 526 527 528 529 530 531 532 533 534 535 536 537 538 | { "sqlite3_memory_highwater", test_memory_highwater }, { "sqlite3_memdebug_backtrace", test_memdebug_backtrace }, { "sqlite3_memdebug_dump", test_memdebug_dump }, { "sqlite3_memdebug_fail", test_memdebug_fail }, { "sqlite3_memdebug_pending", test_memdebug_pending }, { "sqlite3_memdebug_settitle", test_memdebug_settitle }, { "sqlite3_memdebug_malloc_count", test_memdebug_malloc_count }, }; int i; for(i=0; i<sizeof(aObjCmd)/sizeof(aObjCmd[0]); i++){ Tcl_CreateObjCommand(interp, aObjCmd[i].zName, aObjCmd[i].xProc, 0, 0); } return TCL_OK; } | > | 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 | { "sqlite3_memory_highwater", test_memory_highwater }, { "sqlite3_memdebug_backtrace", test_memdebug_backtrace }, { "sqlite3_memdebug_dump", test_memdebug_dump }, { "sqlite3_memdebug_fail", test_memdebug_fail }, { "sqlite3_memdebug_pending", test_memdebug_pending }, { "sqlite3_memdebug_settitle", test_memdebug_settitle }, { "sqlite3_memdebug_malloc_count", test_memdebug_malloc_count }, { "sqlite3_memdebug_log", test_memdebug_log }, }; int i; for(i=0; i<sizeof(aObjCmd)/sizeof(aObjCmd[0]); i++){ Tcl_CreateObjCommand(interp, aObjCmd[i].zName, aObjCmd[i].xProc, 0, 0); } return TCL_OK; } |
Changes to test/tester.tcl.
1 2 3 4 5 6 7 8 9 10 11 12 13 | # 2001 September 15 # # The author disclaims copyright to this source code. In place of # a legal notice, here is a blessing: # # May you do good and not evil. # May you find forgiveness for yourself and forgive others. # May you share freely, never taking more than you give. # #*********************************************************************** # This file implements some common TCL routines used for regression # testing the SQLite library # | | | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | # 2001 September 15 # # The author disclaims copyright to this source code. In place of # a legal notice, here is a blessing: # # May you do good and not evil. # May you find forgiveness for yourself and forgive others. # May you share freely, never taking more than you give. # #*********************************************************************** # This file implements some common TCL routines used for regression # testing the SQLite library # # $Id: tester.tcl,v 1.108 2008/03/21 14:22:44 danielk1977 Exp $ set tcl_precision 15 set sqlite_pending_byte 0x0010000 # # Check the command-line arguments for a default soft-heap-limit. |
︙ | ︙ | |||
642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 | foreach prag {default_cache_size} { append txt $prag-[$db eval "PRAGMA $prag"]\n } # puts txt=$txt return [md5 $txt] } # Copy file $from into $to. This is used because some versions of # TCL for windows (notably the 8.4.1 binary package shipped with the # current mingw release) have a broken "file copy" command. # proc copy_file {from to} { if {$::tcl_platform(platform)=="unix"} { | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 | foreach prag {default_cache_size} { append txt $prag-[$db eval "PRAGMA $prag"]\n } # puts txt=$txt return [md5 $txt] } proc memdebug_log_sql {database} { set data [sqlite3_memdebug_log dump] set nFrame [expr [llength [lindex $data 0]]-2] if {$nFrame < 0} { return "" } set tbl "CREATE TABLE ${database}.malloc(nCall, nByte" for {set ii 1} {$ii <= $nFrame} {incr ii} { append tbl ", f${ii}" } append tbl ");\n" set sql "" foreach e $data { append sql "INSERT INTO ${database}.malloc VALUES([join $e ,]);\n" foreach f [lrange $e 2 end] { set frames($f) 1 } } set tbl2 "CREATE TABLE ${database}.frame(frame INTEGER PRIMARY KEY, line);\n" foreach f [array names frames] { set addr [format %x $f] set cmd "addr2line -e [info nameofexec] $addr" set line [eval exec $cmd] append sql "INSERT INTO ${database}.frame VALUES($f, '$line');\n" } return "BEGIN; ${tbl}${tbl2}${sql} ; COMMIT;" } proc memdebug_log_pp2 {db iLevel iParentFrame iDepth} { set extra 1 if {$iParentFrame != 0} { set extra "f[expr $iLevel-1] = $iParentFrame" } set leader [string repeat " " [expr $iLevel -1]] $db eval " select sum(ncall) calls, sum(nbyte) as bytes, frame, line FROM malloc, frame WHERE f${iLevel}=frame AND $extra GROUP BY f${iLevel} ORDER BY calls DESC " { puts [format "%s%-10s %10s %s" $leader $calls $bytes $line] if {$iLevel < $iDepth} { memdebug_log_pp2 $db [expr $iLevel + 1] $frame $iDepth } } } proc memdebug_log_strip {db} { set nFrame [expr [llength [$db eval "SELECT * FROM malloc LIMIT 1"]] - 2] set update "UPDATE malloc SET " for {set ii 1} {$ii <= $nFrame} {incr ii} { if {$ii == $nFrame} { append update "f${ii} = 0" } else { append update "f${ii} = f[expr $ii+1], " } } append update " WHERE (SELECT line FROM frame WHERE frame = f1) LIKE '%malloc.c:%' OR (SELECT line FROM frame WHERE frame = f1) LIKE '%mem2.c:%' " $db eval $update $db eval $update $db eval $update } proc memdebug_log_pp {{iDepth 1}} { set sql [memdebug_log_sql main] if {$sql eq ""} return sqlite3 mddb :memory: mddb eval $sql memdebug_log_strip mddb memdebug_log_pp2 mddb 1 0 $iDepth mddb close } # Copy file $from into $to. This is used because some versions of # TCL for windows (notably the 8.4.1 binary package shipped with the # current mingw release) have a broken "file copy" command. # proc copy_file {from to} { if {$::tcl_platform(platform)=="unix"} { |
︙ | ︙ |