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