⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 memleak3.tcl

📁 sqlite-3.4.1,嵌入式数据库.是一个功能强大的开源数据库,给学习和研发以及小型公司的发展带来了全所未有的好处.
💻 TCL
字号:
#/bin/sh# \exec `which tclsh` $0 "$@"## 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.######################################################################set doco "This script is a tool to help track down memory leaks in the sqlitelibrary. The library must be compiled with the preprocessor symbolSQLITE_MEMDEBUG set to at least 2. It must be set to 3 to enable stack traces.To use, run the leaky application and save the standard error output.Then, execute this program with the first argument the name of theapplication binary (or interpreter) and the second argument the name of thetext file that contains the collected stderr output.If all goes well a summary of unfreed allocations is printed out. If theGNU C library is in use and SQLITE_DEBUG is 3 or greater a stack trace isprinted out for each unmatched allocation.If the \"-r <n>\" option is passed, then the program stops and prints outthe state of the heap immediately after the <n>th call to malloc() orrealloc().Example:$ ./testfixture ../sqlite/test/select1.test 2> memtrace.out$ tclsh $argv0 ?-r <malloc-number>? ./testfixture memtrace.out"proc usage {} {  set prg [file tail $::argv0]  puts "Usage: $prg ?-r <malloc-number>? <binary file> <mem trace file>"  puts ""  puts [string trim $::doco]  exit -1}proc shift {listvar} {  upvar $listvar l  set ret [lindex $l 0]  set l [lrange $l 1 end]  return $ret}# Argument handling. The following vars are set:## $exe       - the name of the executable (i.e. "testfixture" or "./sqlite3")# $memfile   - the name of the file containing the trace output.# $report_at - The malloc number to stop and report at. Or -1 to read #              all of $memfile.#set report_at -1while {[llength $argv]>2} {  set arg [shift argv]  switch -- $arg {    "-r" {      set report_at [shift argv]    }    default {      usage    }  }}if {[llength $argv]!=2} usageset exe [lindex $argv 0]set memfile [lindex $argv 1]# If stack traces are enabled, the 'addr2line' program is called to# translate a binary stack address into a human-readable form.set addr2line addr2line# When the SQLITE_MEMDEBUG is set as described above, SQLite prints# out a line for each malloc(), realloc() or free() call that the# library makes. If SQLITE_MEMDEBUG is 3, then a stack trace is printed# out before each malloc() and realloc() line.## This program parses each line the SQLite library outputs and updates# the following global Tcl variables to reflect the "current" state of# the heap used by SQLite.#set nBytes 0               ;# Total number of bytes currently allocated.set nMalloc 0              ;# Total number of malloc()/realloc() calls.set nPeak 0                ;# Peak of nBytes.set iPeak 0                ;# nMalloc when nPeak was set.## More detailed state information is stored in the $memmap array. # Each key in the memmap array is the address of a chunk of memory# currently allocated from the heap. The value is a list of the # following form# #     {<number-of-bytes> <malloc id> <stack trace>}#array unset memmapproc process_input {input_file array_name} {  upvar $array_name mem   set input [open $input_file]  set MALLOC {([[:digit:]]+) malloc ([[:digit:]]+) bytes at 0x([[:xdigit:]]+)}  # set STACK {^[[:digit:]]+: STACK: (.*)$}  set STACK {^STACK: (.*)$}  set FREE {[[:digit:]]+ free ([[:digit:]]+) bytes at 0x([[:xdigit:]]+)}  set REALLOC {([[:digit:]]+) realloc ([[:digit:]]+) to ([[:digit:]]+)}  append REALLOC { bytes at 0x([[:xdigit:]]+) to 0x([[:xdigit:]]+)}  set stack ""  while { ![eof $input] } {    set line [gets $input]    if {[regexp $STACK $line dummy stack]} {      # Do nothing. The variable $stack now stores the hexadecimal stack dump      # for the next malloc() or realloc().    } elseif { [regexp $MALLOC $line dummy mallocid bytes addr]  } {      # If this is a 'malloc' line, set an entry in the mem array. Each entry      # is a list of length three, the number of bytes allocated , the malloc      # number and the stack dump when it was allocated.      set mem($addr) [list $bytes "malloc $mallocid" $stack]      set stack ""      # Increase the current heap usage      incr ::nBytes $bytes      # Increase the number of malloc() calls      incr ::nMalloc      if {$::nBytes > $::nPeak} {        set ::nPeak $::nBytes        set ::iPeak $::nMalloc      }    } elseif { [regexp $FREE $line dummy bytes addr] } {      # If this is a 'free' line, remove the entry from the mem array. If the       # entry does not exist, or is the wrong number of bytes, announce a      # problem. This is more likely a bug in the regular expressions for      # this script than an SQLite defect.      if { [lindex $mem($addr) 0] != $bytes } {        error "byte count mismatch"      }      unset mem($addr)       # Decrease the current heap usage      incr ::nBytes [expr -1 * $bytes]    } elseif { [regexp $REALLOC $line dummy mallocid ob b oa a] } {      # "free" the old allocation in the internal model:      incr ::nBytes [expr -1 * $ob]      unset mem($oa);      # "malloc" the new allocation      set mem($a) [list $b "realloc $mallocid" $stack]      incr ::nBytes $b      set stack ""      # Increase the number of malloc() calls      incr ::nMalloc      if {$::nBytes > $::nPeak} {        set ::nPeak $::nBytes        set ::iPeak $::nMalloc      }    } else {      # puts "REJECT: $line"    }    if {$::nMalloc==$::report_at} report  }  close $input}proc printstack {stack} {  set fcount 10  if {[llength $stack]<10} {    set fcount [llength $stack]  }  foreach frame [lrange $stack 1 $fcount] {    foreach {f l} [split [exec $::addr2line -f --exe=$::exe $frame] \n] {}    puts [format "%-30s %s" $f $l]  }  if {[llength $stack]>0 } {puts ""}}proc report {} {  foreach key [array names ::memmap] {    set stack [lindex $::memmap($key) 2]    set bytes [lindex $::memmap($key) 0]    lappend summarymap($stack) $bytes  }  set sorted [list]  foreach stack [array names summarymap] {    set allocs $summarymap($stack)    set sum 0    foreach a $allocs {      incr sum $a    }    lappend sorted [list $sum $stack]  }  set sorted [lsort -integer -index 0 $sorted]  foreach s $sorted {    set sum [lindex $s 0]    set stack [lindex $s 1]    set allocs $summarymap($stack)    puts "$sum bytes in [llength $allocs] chunks ($allocs)"    printstack $stack  }  # Print out summary statistics  puts "Total allocations            : $::nMalloc"  puts "Total outstanding allocations: [array size ::memmap]"   puts "Current heap usage           : $::nBytes bytes"  puts "Peak heap usage              : $::nPeak bytes (malloc #$::iPeak)"  exit}process_input $memfile memmapreport

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -