1*c1c95addSBrooks Davis.\" $Id: mandoc_dbg_init.3,v 1.1 2022/04/14 16:43:44 schwarze Exp $ 2*c1c95addSBrooks Davis.\" 3*c1c95addSBrooks Davis.\" Copyright (c) 2021, 2022 Ingo Schwarze <schwarze@openbsd.org> 4*c1c95addSBrooks Davis.\" 5*c1c95addSBrooks Davis.\" Permission to use, copy, modify, and distribute this software for any 6*c1c95addSBrooks Davis.\" purpose with or without fee is hereby granted, provided that the above 7*c1c95addSBrooks Davis.\" copyright notice and this permission notice appear in all copies. 8*c1c95addSBrooks Davis.\" 9*c1c95addSBrooks Davis.\" THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 10*c1c95addSBrooks Davis.\" WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 11*c1c95addSBrooks Davis.\" MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 12*c1c95addSBrooks Davis.\" ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 13*c1c95addSBrooks Davis.\" WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 14*c1c95addSBrooks Davis.\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 15*c1c95addSBrooks Davis.\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 16*c1c95addSBrooks Davis.\" 17*c1c95addSBrooks Davis.Dd $Mdocdate: April 14 2022 $ 18*c1c95addSBrooks Davis.Dt MANDOC_DBG_INIT 3 19*c1c95addSBrooks Davis.Os 20*c1c95addSBrooks Davis.Sh NAME 21*c1c95addSBrooks Davis.Nm mandoc_dbg_init , 22*c1c95addSBrooks Davis.Nm mandoc_dbg_name , 23*c1c95addSBrooks Davis.Nm mandoc_dbg_finish 24*c1c95addSBrooks Davis.Nd search for memory leaks in mandoc 25*c1c95addSBrooks Davis.Sh SYNOPSIS 26*c1c95addSBrooks Davis.Ft void 27*c1c95addSBrooks Davis.Fn mandoc_dbg_init "int argc" "char *argv[]" 28*c1c95addSBrooks Davis.Ft void 29*c1c95addSBrooks Davis.Fn mandoc_dbg_name "const char *" 30*c1c95addSBrooks Davis.Ft void 31*c1c95addSBrooks Davis.Fn mandoc_dbg_finish void 32*c1c95addSBrooks Davis.Sh DESCRIPTION 33*c1c95addSBrooks DavisIf the mandoc package is built with the line 34*c1c95addSBrooks Davis.Ql DEBUG_MEMORY=1 35*c1c95addSBrooks Davisin the file 36*c1c95addSBrooks Davis.Pa configure.local , 37*c1c95addSBrooks Davisthe functions documented in 38*c1c95addSBrooks Davis.Xr mandoc_malloc 3 39*c1c95addSBrooks Davisand the function 40*c1c95addSBrooks Davis.Xr free 3 41*c1c95addSBrooks Davisare instrumented to record every memory allocation in a dedicated 42*c1c95addSBrooks Davishash table and to check that every allocation is freed again. 43*c1c95addSBrooks DavisThis compile time option is only intended for binaries that are 44*c1c95addSBrooks Davisused exclusively for debugging. 45*c1c95addSBrooks DavisIt is not intended for production binaries because it significantly 46*c1c95addSBrooks Davisincreases run time and memory usage and makes the programs more 47*c1c95addSBrooks Davisfragile and more error-prone. 48*c1c95addSBrooks Davis.Pp 49*c1c95addSBrooks DavisThe function 50*c1c95addSBrooks Davis.Fn mandoc_dbg_init 51*c1c95addSBrooks Davisinitializes the memory debugging subsystem. 52*c1c95addSBrooks DavisIt is called from the top of the 53*c1c95addSBrooks Davis.Fn main 54*c1c95addSBrooks Davisprograms, passing through the arguments that 55*c1c95addSBrooks Davis.Fn main 56*c1c95addSBrooks Davisreceived. 57*c1c95addSBrooks DavisThe 58*c1c95addSBrooks Davis.Sx ENVIRONMENT 59*c1c95addSBrooks Davissection of the present manual page explains how the 60*c1c95addSBrooks Davis.Ev DEBUG_MEMORY 61*c1c95addSBrooks Davisenvironment variable controls the amount and destination of reporting. 62*c1c95addSBrooks Davis.Pp 63*c1c95addSBrooks DavisThe function 64*c1c95addSBrooks Davis.Fn mandoc_dbg_name 65*c1c95addSBrooks Davisis called from the 66*c1c95addSBrooks Davis.Xr mdoc 7 67*c1c95addSBrooks Davisand 68*c1c95addSBrooks Davis.Xr man 7 69*c1c95addSBrooks Davisparsers whenever a 70*c1c95addSBrooks Davis.Ic \&Dt 71*c1c95addSBrooks Davisor 72*c1c95addSBrooks Davis.Ic \&TH 73*c1c95addSBrooks Davismacro is parsed, passing the complete macro line as the argument. 74*c1c95addSBrooks Davis.Pp 75*c1c95addSBrooks DavisThe function 76*c1c95addSBrooks Davis.Fn mandoc_dbg_finish 77*c1c95addSBrooks Davisperforms cleanup and optionally final reporting. 78*c1c95addSBrooks DavisIt is called from the end of the 79*c1c95addSBrooks Davis.Fn main 80*c1c95addSBrooks Davisprograms, just before normal termination. 81*c1c95addSBrooks Davis.Pp 82*c1c95addSBrooks DavisGetting the 83*c1c95addSBrooks Davis.Sy #include 84*c1c95addSBrooks Davisdirectives right for these functions is slightly tricky. 85*c1c95addSBrooks DavisIf a file already includes 86*c1c95addSBrooks Davis.Qq Pa mandoc_aux.h , 87*c1c95addSBrooks Davisno additional directive is needed because 88*c1c95addSBrooks Davis.Qq Pa mandoc_aux.h 89*c1c95addSBrooks Davisalready includes 90*c1c95addSBrooks Davis.Qq Pa mandoc_dgb.h 91*c1c95addSBrooks Davisif 92*c1c95addSBrooks Davis.Ql DEBUG_MEMORY=1 93*c1c95addSBrooks Davisis set in 94*c1c95addSBrooks Davis.Pa configure.local . 95*c1c95addSBrooks Davis.Pp 96*c1c95addSBrooks DavisIf a file does not need 97*c1c95addSBrooks Davis.Qq Pa mandoc_aux.h 98*c1c95addSBrooks Davisbut calls a function documented in the present manual page and also calls 99*c1c95addSBrooks Davis.Xr free 3 100*c1c95addSBrooks Davisdirectly, it needs this code before the other 101*c1c95addSBrooks Davis.Xr mandoc_headers 3 : 102*c1c95addSBrooks Davis.Bd -literal -offset indent 103*c1c95addSBrooks Davis#if DEBUG_MEMORY 104*c1c95addSBrooks Davis#include "mandoc_dbg.h" 105*c1c95addSBrooks Davis#endif 106*c1c95addSBrooks Davis.Ed 107*c1c95addSBrooks Davis.Pp 108*c1c95addSBrooks DavisIf a file calls a function documented in the present manual page 109*c1c95addSBrooks Davisbut does not directly call 110*c1c95addSBrooks Davis.Xr free 3 , 111*c1c95addSBrooks Davisit can use this less intrusive idiom: 112*c1c95addSBrooks Davis.Bd -literal -offset indent 113*c1c95addSBrooks Davis#if DEBUG_MEMORY 114*c1c95addSBrooks Davis#define DEBUG_NODEF 115*c1c95addSBrooks Davis#include "mandoc_dbg.h" 116*c1c95addSBrooks Davis#endif 117*c1c95addSBrooks Davis.Ed 118*c1c95addSBrooks Davis.Sh ENVIRONMENT 119*c1c95addSBrooks DavisThe environment variable 120*c1c95addSBrooks Davis.Ev DEBUG_MEMORY 121*c1c95addSBrooks Daviscontrols the amount and destination of reporting. 122*c1c95addSBrooks Davis.Pp 123*c1c95addSBrooks DavisIf it is unset, diagnostic output is directed to standard error output 124*c1c95addSBrooks Davisand only fatal errors are reported. 125*c1c95addSBrooks DavisEven though full memory accounting is always performed 126*c1c95addSBrooks Davisby any binary that was compiled with 127*c1c95addSBrooks Davis.Ql DEBUG_MEMORY=1 , 128*c1c95addSBrooks Davisresulting in a significant increase in both run time and memory usage, 129*c1c95addSBrooks Davismemory leaks are 130*c1c95addSBrooks Davis.Em not 131*c1c95addSBrooks Davisreported when 132*c1c95addSBrooks Davis.Ev DEBUG_MEMORY 133*c1c95addSBrooks Davisis not set at run time. 134*c1c95addSBrooks Davis.Pp 135*c1c95addSBrooks DavisIf 136*c1c95addSBrooks Davis.Ev DEBUG_MEMORY 137*c1c95addSBrooks Davisis set, it is interpreted as a string of flags. 138*c1c95addSBrooks DavisThe flags are as follows: 139*c1c95addSBrooks Davis.Bl -tag -width 1n 140*c1c95addSBrooks Davis.It Cm A 141*c1c95addSBrooks DavisLog every allocation. 142*c1c95addSBrooks DavisThis produces huge amounts of output and is usually not needed 143*c1c95addSBrooks Davisto find memory leaks. 144*c1c95addSBrooks DavisIts main purpose is debugging the memory debugging subsystem itself. 145*c1c95addSBrooks Davis.Pp 146*c1c95addSBrooks DavisWhen enabled, allocations are logged in this format: 147*c1c95addSBrooks Davis.Pp 148*c1c95addSBrooks Davis.D1 Cm A Ar file Ns .c: Ns Ar line function Ns Po Fa nmemb , size Pc\ 149*c1c95addSBrooks Davis No = Ar address 150*c1c95addSBrooks Davis.Pp 151*c1c95addSBrooks DavisThe meaning of the fields is the same as for the 152*c1c95addSBrooks Davis.Cm L 153*c1c95addSBrooks Davisoption. 154*c1c95addSBrooks Davis.It Cm F 155*c1c95addSBrooks DavisLog every 156*c1c95addSBrooks Davis.Xr free 3 157*c1c95addSBrooks Davisand every reallocation where the memory to be released or reallocated 158*c1c95addSBrooks Daviswas allocated with one of the functions documented in 159*c1c95addSBrooks Davis.Xr mandoc_malloc 3 . 160*c1c95addSBrooks DavisAgain, this produces huge amounts of output and is usually not 161*c1c95addSBrooks Davisneeded to find memory leaks, and its main purpose is debugging the 162*c1c95addSBrooks Davismemory debugging subsystem itself. 163*c1c95addSBrooks Davis.Pp 164*c1c95addSBrooks DavisThe logging format is: 165*c1c95addSBrooks Davis.Pp 166*c1c95addSBrooks Davis.D1 Cm F Ar file Ns .c: Ns Ar line function Ns Pq address 167*c1c95addSBrooks Davis.Pp 168*c1c95addSBrooks DavisIt provides the name of the 169*c1c95addSBrooks Davis.Ar file 170*c1c95addSBrooks Davisand the number of the 171*c1c95addSBrooks Davis.Ar line 172*c1c95addSBrooks Davisin that file which called the 173*c1c95addSBrooks Davis.Xr free 3 174*c1c95addSBrooks Davisor reallocation 175*c1c95addSBrooks Davis.Ar function , 176*c1c95addSBrooks Davisand the 177*c1c95addSBrooks Davis.Fa address 178*c1c95addSBrooks Davisthat was given as an argument. 179*c1c95addSBrooks Davis.Pp 180*c1c95addSBrooks DavisIf both the 181*c1c95addSBrooks Davis.Cm A 182*c1c95addSBrooks Davisand the 183*c1c95addSBrooks Davis.Cm F 184*c1c95addSBrooks Davisflags are enabled, calls to reallocation functions often log two lines, 185*c1c95addSBrooks Davisfirst an 186*c1c95addSBrooks Davis.Cm F 187*c1c95addSBrooks Davisline reporting the address passed in as an argument, then an 188*c1c95addSBrooks Davis.Cm A 189*c1c95addSBrooks Davisline reporting the adress returned as the function return value. 190*c1c95addSBrooks Davis.It Cm L 191*c1c95addSBrooks DavisLog every memory leak. 192*c1c95addSBrooks DavisFor every allocation made after 193*c1c95addSBrooks Davis.Fn mandoc_dbg_init 194*c1c95addSBrooks Davisusing functions documented in 195*c1c95addSBrooks Davis.Xr mandoc_malloc 3 196*c1c95addSBrooks Davisthat was not freed before 197*c1c95addSBrooks Davis.Fn mandoc_dbg_finish , 198*c1c95addSBrooks Davisprint a line in this format: 199*c1c95addSBrooks Davis.Pp 200*c1c95addSBrooks Davis.D1 Cm L Ar file Ns .c: Ns Ar line function Ns Po Fa nmemb , size Pc\ 201*c1c95addSBrooks Davis No = Ar address 202*c1c95addSBrooks Davis.Pp 203*c1c95addSBrooks DavisIt provides the name of the 204*c1c95addSBrooks Davis.Ar file 205*c1c95addSBrooks Davisand the number of the 206*c1c95addSBrooks Davis.Ar line 207*c1c95addSBrooks Davisin that file which called the allocation 208*c1c95addSBrooks Davis.Ar function 209*c1c95addSBrooks Daviswith the arguments 210*c1c95addSBrooks Davis.Fa nmemb 211*c1c95addSBrooks Davisand 212*c1c95addSBrooks Davis.Fa size 213*c1c95addSBrooks Davisdocumented for 214*c1c95addSBrooks Davis.Xr calloc 3 . 215*c1c95addSBrooks DavisIf the 216*c1c95addSBrooks Davis.Ar function 217*c1c95addSBrooks Davisdoes not take an 218*c1c95addSBrooks Davis.Fa nmemb 219*c1c95addSBrooks Davisargument, 220*c1c95addSBrooks Davis.Fa nmemb 221*c1c95addSBrooks Davisis reported as 1. 222*c1c95addSBrooks DavisAt the end of the line, the virtual 223*c1c95addSBrooks Davis.Ar address 224*c1c95addSBrooks Davisof the memory returned from the allocation function is reported. 225*c1c95addSBrooks Davis.It Cm N 226*c1c95addSBrooks DavisLog the names of manual pages processed in the following formats: 227*c1c95addSBrooks Davis.Bd -unfilled -offset indent 228*c1c95addSBrooks Davis.Cm N Pf . Ic \&Dt Ar name section Op Ar architecture 229*c1c95addSBrooks Davis.Cm N Pf . Ic \&TH Ar name section Op Ar additional arguments 230*c1c95addSBrooks Davis.Ed 231*c1c95addSBrooks Davis.Pp 232*c1c95addSBrooks DavisThis is particularly useful if a program crashes, runs out of memory, 233*c1c95addSBrooks Davisor enters an infinite loop. 234*c1c95addSBrooks DavisThe last 235*c1c95addSBrooks Davis.Cm N 236*c1c95addSBrooks Davisline logged often indicates the input file triggering the problem. 237*c1c95addSBrooks Davis.It Cm / 238*c1c95addSBrooks DavisInterpret the rest of 239*c1c95addSBrooks Davis.Ev DEBUG_MEMORY 240*c1c95addSBrooks Davisas an absolute path and redirect debugging output to that file, 241*c1c95addSBrooks Davisappending to the file if it already exists or creating it otherwise. 242*c1c95addSBrooks Davis.El 243*c1c95addSBrooks Davis.Pp 244*c1c95addSBrooks DavisIf 245*c1c95addSBrooks Davis.Ev DEBUG_MEMORY 246*c1c95addSBrooks Davisis set, even if it is empty, 247*c1c95addSBrooks Davis.Fn mandoc_dbg_init 248*c1c95addSBrooks Davisalways writes the line 249*c1c95addSBrooks Davis.Pp 250*c1c95addSBrooks Davis.D1 Cm P Ar pid Sy \&[ Ns Ar progname Ns Sy \&]\ 251*c1c95addSBrooks Davis Sy \&[ Ns Ar argument Ns Sy \&] Ar ... 252*c1c95addSBrooks Davis.Pp 253*c1c95addSBrooks Davisenclosing each element of 254*c1c95addSBrooks Davis.Fa argv 255*c1c95addSBrooks Davisin square brackets, to avoid that arguments containing whitespace 256*c1c95addSBrooks Davisappear in the same way as multiple arguments, and 257*c1c95addSBrooks Davis.Fn mandoc_dbg_finish 258*c1c95addSBrooks Davisalways writes the line: 259*c1c95addSBrooks Davis.Pp 260*c1c95addSBrooks Davis.D1 Cm S Ar number No memory leaks found 261*c1c95addSBrooks Davis.Sh EXAMPLES 262*c1c95addSBrooks DavisThe following is a typical sequence of commands for finding memory 263*c1c95addSBrooks Davisleaks in the parsers, in the HTML formatter, and in the regression suite: 264*c1c95addSBrooks Davis.Bd -literal -offset indent 265*c1c95addSBrooks Davismake distclean 266*c1c95addSBrooks Davisecho BUILD_CATMAN=1 >> configure.local 267*c1c95addSBrooks Davisecho DEBUG_MEMORY=1 >> configure.local 268*c1c95addSBrooks Davis\&./configure 269*c1c95addSBrooks Davismake 270*c1c95addSBrooks Davisexport DEBUG_MEMORY=NL/tmp/mandoc.debug.txt 271*c1c95addSBrooks Davismkdir Out 272*c1c95addSBrooks Davisexport PATH=$PATH:$(pwd) 273*c1c95addSBrooks Davis\&./catman -T html /usr/share/man Out 274*c1c95addSBrooks Davismake regress-clean 275*c1c95addSBrooks Davismake regress 276*c1c95addSBrooks Davisless /tmp/mandoc.debug.txt 277*c1c95addSBrooks Davis.Ed 278*c1c95addSBrooks Davis.Sh SEE ALSO 279*c1c95addSBrooks Davis.Xr mandoc_malloc 3 , 280*c1c95addSBrooks Davis.Xr catman 8 281