.\" $Id: mandoc_dbg_init.3,v 1.1 2022/04/14 16:43:44 schwarze Exp $ .\" .\" Copyright (c) 2021, 2022 Ingo Schwarze .\" .\" Permission to use, copy, modify, and distribute this software for any .\" purpose with or without fee is hereby granted, provided that the above .\" copyright notice and this permission notice appear in all copies. .\" .\" THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES .\" WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF .\" MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR .\" ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES .\" WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN .\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF .\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. .\" .Dd $Mdocdate: April 14 2022 $ .Dt MANDOC_DBG_INIT 3 .Os .Sh NAME .Nm mandoc_dbg_init , .Nm mandoc_dbg_name , .Nm mandoc_dbg_finish .Nd search for memory leaks in mandoc .Sh SYNOPSIS .Ft void .Fn mandoc_dbg_init "int argc" "char *argv[]" .Ft void .Fn mandoc_dbg_name "const char *" .Ft void .Fn mandoc_dbg_finish void .Sh DESCRIPTION If the mandoc package is built with the line .Ql DEBUG_MEMORY=1 in the file .Pa configure.local , the functions documented in .Xr mandoc_malloc 3 and the function .Xr free 3 are instrumented to record every memory allocation in a dedicated hash table and to check that every allocation is freed again. This compile time option is only intended for binaries that are used exclusively for debugging. It is not intended for production binaries because it significantly increases run time and memory usage and makes the programs more fragile and more error-prone. .Pp The function .Fn mandoc_dbg_init initializes the memory debugging subsystem. It is called from the top of the .Fn main programs, passing through the arguments that .Fn main received. The .Sx ENVIRONMENT section of the present manual page explains how the .Ev DEBUG_MEMORY environment variable controls the amount and destination of reporting. .Pp The function .Fn mandoc_dbg_name is called from the .Xr mdoc 7 and .Xr man 7 parsers whenever a .Ic \&Dt or .Ic \&TH macro is parsed, passing the complete macro line as the argument. .Pp The function .Fn mandoc_dbg_finish performs cleanup and optionally final reporting. It is called from the end of the .Fn main programs, just before normal termination. .Pp Getting the .Sy #include directives right for these functions is slightly tricky. If a file already includes .Qq Pa mandoc_aux.h , no additional directive is needed because .Qq Pa mandoc_aux.h already includes .Qq Pa mandoc_dgb.h if .Ql DEBUG_MEMORY=1 is set in .Pa configure.local . .Pp If a file does not need .Qq Pa mandoc_aux.h but calls a function documented in the present manual page and also calls .Xr free 3 directly, it needs this code before the other .Xr mandoc_headers 3 : .Bd -literal -offset indent #if DEBUG_MEMORY #include "mandoc_dbg.h" #endif .Ed .Pp If a file calls a function documented in the present manual page but does not directly call .Xr free 3 , it can use this less intrusive idiom: .Bd -literal -offset indent #if DEBUG_MEMORY #define DEBUG_NODEF #include "mandoc_dbg.h" #endif .Ed .Sh ENVIRONMENT The environment variable .Ev DEBUG_MEMORY controls the amount and destination of reporting. .Pp If it is unset, diagnostic output is directed to standard error output and only fatal errors are reported. Even though full memory accounting is always performed by any binary that was compiled with .Ql DEBUG_MEMORY=1 , resulting in a significant increase in both run time and memory usage, memory leaks are .Em not reported when .Ev DEBUG_MEMORY is not set at run time. .Pp If .Ev DEBUG_MEMORY is set, it is interpreted as a string of flags. The flags are as follows: .Bl -tag -width 1n .It Cm A Log every allocation. This produces huge amounts of output and is usually not needed to find memory leaks. Its main purpose is debugging the memory debugging subsystem itself. .Pp When enabled, allocations are logged in this format: .Pp .D1 Cm A Ar file Ns .c: Ns Ar line function Ns Po Fa nmemb , size Pc\ No = Ar address .Pp The meaning of the fields is the same as for the .Cm L option. .It Cm F Log every .Xr free 3 and every reallocation where the memory to be released or reallocated was allocated with one of the functions documented in .Xr mandoc_malloc 3 . Again, this produces huge amounts of output and is usually not needed to find memory leaks, and its main purpose is debugging the memory debugging subsystem itself. .Pp The logging format is: .Pp .D1 Cm F Ar file Ns .c: Ns Ar line function Ns Pq address .Pp It provides the name of the .Ar file and the number of the .Ar line in that file which called the .Xr free 3 or reallocation .Ar function , and the .Fa address that was given as an argument. .Pp If both the .Cm A and the .Cm F flags are enabled, calls to reallocation functions often log two lines, first an .Cm F line reporting the address passed in as an argument, then an .Cm A line reporting the adress returned as the function return value. .It Cm L Log every memory leak. For every allocation made after .Fn mandoc_dbg_init using functions documented in .Xr mandoc_malloc 3 that was not freed before .Fn mandoc_dbg_finish , print a line in this format: .Pp .D1 Cm L Ar file Ns .c: Ns Ar line function Ns Po Fa nmemb , size Pc\ No = Ar address .Pp It provides the name of the .Ar file and the number of the .Ar line in that file which called the allocation .Ar function with the arguments .Fa nmemb and .Fa size documented for .Xr calloc 3 . If the .Ar function does not take an .Fa nmemb argument, .Fa nmemb is reported as 1. At the end of the line, the virtual .Ar address of the memory returned from the allocation function is reported. .It Cm N Log the names of manual pages processed in the following formats: .Bd -unfilled -offset indent .Cm N Pf . Ic \&Dt Ar name section Op Ar architecture .Cm N Pf . Ic \&TH Ar name section Op Ar additional arguments .Ed .Pp This is particularly useful if a program crashes, runs out of memory, or enters an infinite loop. The last .Cm N line logged often indicates the input file triggering the problem. .It Cm / Interpret the rest of .Ev DEBUG_MEMORY as an absolute path and redirect debugging output to that file, appending to the file if it already exists or creating it otherwise. .El .Pp If .Ev DEBUG_MEMORY is set, even if it is empty, .Fn mandoc_dbg_init always writes the line .Pp .D1 Cm P Ar pid Sy \&[ Ns Ar progname Ns Sy \&]\ Sy \&[ Ns Ar argument Ns Sy \&] Ar ... .Pp enclosing each element of .Fa argv in square brackets, to avoid that arguments containing whitespace appear in the same way as multiple arguments, and .Fn mandoc_dbg_finish always writes the line: .Pp .D1 Cm S Ar number No memory leaks found .Sh EXAMPLES The following is a typical sequence of commands for finding memory leaks in the parsers, in the HTML formatter, and in the regression suite: .Bd -literal -offset indent make distclean echo BUILD_CATMAN=1 >> configure.local echo DEBUG_MEMORY=1 >> configure.local \&./configure make export DEBUG_MEMORY=NL/tmp/mandoc.debug.txt mkdir Out export PATH=$PATH:$(pwd) \&./catman -T html /usr/share/man Out make regress-clean make regress less /tmp/mandoc.debug.txt .Ed .Sh SEE ALSO .Xr mandoc_malloc 3 , .Xr catman 8