Skip to content

Commit 6882103

Browse files
committed
follow-up to 584e2a1 - configurable signal, refactoring, add tests
1 parent 584e2a1 commit 6882103

14 files changed

+304
-124
lines changed

CMakeLists.txt

+15-5
Original file line numberDiff line numberDiff line change
@@ -23,12 +23,10 @@ set(CMAKE_CXX_STANDARD_REQUIRED ON)
2323
set(CMAKE_POSITION_INDEPENDENT_CODE ON)
2424

2525
# Library
26-
add_library(heapusage SHARED src/humain.cpp src/hulog.cpp src/humalloc.cpp src/huapi.cpp)
27-
set_target_properties(heapusage PROPERTIES PUBLIC_HEADER "src/huapi.h")
26+
add_library(heapusage SHARED src/humain.cpp src/hulog.cpp src/humalloc.cpp)
27+
set_target_properties(heapusage PROPERTIES PUBLIC_HEADER "src/heapusage.h")
2828
target_compile_features(heapusage PRIVATE cxx_variadic_templates)
29-
install(TARGETS heapusage
30-
LIBRARY DESTINATION lib
31-
PUBLIC_HEADER DESTINATION ${CMAKE_INSTALL_INCLUDEDIR})
29+
install(TARGETS heapusage LIBRARY DESTINATION lib PUBLIC_HEADER DESTINATION include)
3230
target_link_libraries(heapusage pthread dl)
3331

3432
# Dependency backward-cpp providing more detailed stacktraces on Linux, when
@@ -49,17 +47,23 @@ install(FILES src/heapusage.1 DESTINATION share/man/man1)
4947
# Tests
5048
enable_testing()
5149

50+
include_directories("src")
5251
add_executable(ex001 tests/ex001.c)
5352
add_executable(ex002 tests/ex002.c)
5453
add_executable(ex003 tests/ex003.cpp)
5554
add_executable(ex004 tests/ex004.cpp)
5655
add_executable(ex005 tests/ex005.cpp)
56+
add_executable(ex006 tests/ex006.cpp)
57+
add_executable(ex007 tests/ex007.cpp src/heapusage.h)
5758

5859
target_compile_options(ex001 PRIVATE -O0)
5960
target_compile_options(ex002 PRIVATE -O0)
6061
target_compile_options(ex003 PRIVATE -O0)
6162
target_compile_options(ex004 PRIVATE -O0)
6263
target_compile_options(ex005 PRIVATE -O0)
64+
target_compile_options(ex006 PRIVATE -O0)
65+
target_compile_options(ex007 PRIVATE -O0)
66+
target_link_libraries(ex007 heapusage)
6367

6468
configure_file(tests/test001 ${CMAKE_CURRENT_BINARY_DIR}/test001 COPYONLY)
6569
add_test(test001 "${PROJECT_BINARY_DIR}/test001")
@@ -75,3 +79,9 @@ add_test(test004 "${PROJECT_BINARY_DIR}/test004")
7579

7680
configure_file(tests/test005 ${CMAKE_CURRENT_BINARY_DIR}/test005 COPYONLY)
7781
add_test(test005 "${PROJECT_BINARY_DIR}/test005")
82+
83+
configure_file(tests/test006 ${CMAKE_CURRENT_BINARY_DIR}/test006 COPYONLY)
84+
add_test(test006 "${PROJECT_BINARY_DIR}/test006")
85+
86+
configure_file(tests/test007 ${CMAKE_CURRENT_BINARY_DIR}/test007 COPYONLY)
87+
add_test(test007 "${PROJECT_BINARY_DIR}/test007")

README.md

+18-14
Original file line numberDiff line numberDiff line change
@@ -101,6 +101,9 @@ Options:
101101
-o <path>
102102
write output to specified file path, instead of stderr
103103

104+
-s <SIG>
105+
enable on-demand logging when signalled SIG signal
106+
104107
-t <tools>
105108
analysis tools to use (default "leak")
106109

@@ -136,20 +139,6 @@ Examples:
136139
heapusage -t all -m 0 ./ex002
137140
analyze heap allocations of any size with all tools.
138141

139-
Programs being ran with Heapusage can themselves also request reports from
140-
Heapusage, while the program is running, by using the `hu_report()` public API
141-
function. For doing so, they must include the `huapi.h` public header file, link
142-
with the Heapusage shared library itself and call `hu_report()` when wanted.
143-
Still, this only works if the program is running through the `heapusage` tool.
144-
145-
Alternatively, on Linux, sending a `SIGUSR1` signal to the program being run
146-
through Heapusage will also produce a Heapusage report on demand.
147-
148-
For both `hu_report()` and `SIGUSR1`, it should be noted that the report will
149-
reflect the state when they are used, which can e.g. report non-freed memory
150-
that might be still released before the program exits and, therefore, not
151-
necessarily constitute a memory leak.
152-
153142
Output Format
154143
=============
155144
Example output:
@@ -181,6 +170,21 @@ Source code filename and line numbers are only supported on Linux, when package
181170
binutils-dev is available. On macOS one can use atos to determine source code
182171
details.
183172

173+
Advanced Usage
174+
==============
175+
On-demand report can be requested by utilizing the `-s` flag and specifying a
176+
signal, and the sending the signal to the process. Example:
177+
178+
./build/heapusage -s SIGUSR1 -t all -m 0 -o hu.txt nano
179+
kill -s SIGUSR1 $(pidof nano)
180+
181+
Programs can also link libheapusage and call `hu_report()` for an on-demand
182+
report, see `tests/ex007.cpp` for an example.
183+
184+
Note that on-demand reporting will reflect the state when they are used, and
185+
will thus report memory currently in use that might still be released before
186+
the program exits, and therefore not necessarily constitute a memory leak.
187+
184188
Technical Details
185189
=================
186190
Heapusage intercepts calls to malloc/free/calloc/realloc and logs each memory

src/heapusage

+19-3
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ showusage()
1010
echo "Heapusage is a light-weight tool for finding heap memory errors in"
1111
echo "applications."
1212
echo ""
13-
echo "Usage: heapusage [-d] [-m minsize] [-n] [-o path] [-t tools] PROG [ARGS..]"
13+
echo "Usage: heapusage [-d] [-m minsize] [-n] [-o path] [-s SIG] [-t tools] PROG [ARGS..]"
1414
echo " or: heapusage --help"
1515
echo " or: heapusage --version"
1616
echo ""
@@ -19,6 +19,7 @@ showusage()
1919
echo " -m <minsize> min alloc size to enable analysis for (default 0)"
2020
echo " -n no symbol lookup (faster)"
2121
echo " -o <path> write output to specified file path, instead of stderr"
22+
echo " -s <SIG> enable on-demand logging when signalled SIG signal"
2223
echo " -t <tools> analysis tools to use (default \"leak\")"
2324
echo " PROG program to run and analyze"
2425
echo " [ARGS] optional arguments to the program"
@@ -46,7 +47,7 @@ showusage()
4647

4748
showversion()
4849
{
49-
echo "heapusage v2.09"
50+
echo "heapusage v2.10"
5051
echo ""
5152
echo "Copyright (C) 2017-2024 Kristofer Berggren"
5253
echo ""
@@ -72,8 +73,9 @@ DEBUG="0"
7273
MINSIZE="0"
7374
NOSYMS="0"
7475
OUTFILE=""
76+
SIGNO=""
7577
TOOLS="leak"
76-
while getopts "?dfm:no:t:" OPT; do
78+
while getopts "?dfm:no:s:t:" OPT; do
7779
case "${OPT}" in
7880
\?)
7981
showusage
@@ -91,6 +93,18 @@ while getopts "?dfm:no:t:" OPT; do
9193
o)
9294
OUTFILE="${OPTARG}"
9395
;;
96+
s)
97+
if ! [[ "${OPTARG}" =~ ^[0-9]+$ ]]; then
98+
# Not a number, try signal name
99+
SIGNO="$(kill -l ${OPTARG} 2> /dev/null)"
100+
if [[ "${SIGNO}" == "" ]]; then
101+
echo "error: unknown signal name ${OPTARG}"
102+
exit 1
103+
fi
104+
else
105+
SIGNO="${OPTARG}"
106+
fi
107+
;;
94108
t)
95109
TOOLS="${OPTARG}"
96110
;;
@@ -201,6 +215,7 @@ while [ "${LIBPATHS[CNT]}" != "" ]; do
201215
HU_FILE="${TMPLOG}${OUTFILE}" \
202216
HU_MINSIZE="${MINSIZE}" \
203217
HU_NOSYMS="${NOSYMS}" \
218+
HU_SIGNO="${SIGNO}" \
204219
LD_PRELOAD="${LIBPATH}" \
205220
DYLD_INSERT_LIBRARIES="${LIBPATH}" \
206221
DYLD_FORCE_FLAT_NAMESPACE=1 \
@@ -214,6 +229,7 @@ while [ "${LIBPATHS[CNT]}" != "" ]; do
214229
echo "env HU_FILE=\"${TMPLOG}${OUTFILE}\"" >> "${LLDBCMDPATH}"
215230
echo "env HU_MINSIZE=\"${MINSIZE}\"" >> "${LLDBCMDPATH}"
216231
echo "env HU_NOSYMS=\"${NOSYMS}\"" >> "${LLDBCMDPATH}"
232+
echo "env HU_SIGNO=\"${SIGNO}\"" >> "${LLDBCMDPATH}"
217233
echo "env LD_PRELOAD=\"${LIBPATH}\"" >> "${LLDBCMDPATH}"
218234
echo "env DYLD_INSERT_LIBRARIES=\"${LIBPATH}\"" >> "${LLDBCMDPATH}"
219235
echo "env DYLD_FORCE_FLAT_NAMESPACE=1" >> "${LLDBCMDPATH}"

src/heapusage.1

+5-2
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
11
.\" DO NOT MODIFY THIS FILE! It was generated by help2man.
2-
.TH HEAPUSAGE "1" "June 2024" "heapusage v2.09" "User Commands"
2+
.TH HEAPUSAGE "1" "June 2024" "heapusage v2.10" "User Commands"
33
.SH NAME
44
heapusage \- find memory leaks in applications
55
.SH SYNOPSIS
66
.B heapusage
7-
[\fI\,-d\/\fR] [\fI\,-m minsize\/\fR] [\fI\,-n\/\fR] [\fI\,-o path\/\fR] [\fI\,-t tools\/\fR] \fI\,PROG \/\fR[\fI\,ARGS\/\fR..]
7+
[\fI\,-d\/\fR] [\fI\,-m minsize\/\fR] [\fI\,-n\/\fR] [\fI\,-o path\/\fR] [\fI\,-s SIG\/\fR] [\fI\,-t tools\/\fR] \fI\,PROG \/\fR[\fI\,ARGS\/\fR..]
88
.br
99
.B heapusage
1010
\fI\,--help\/\fR
@@ -28,6 +28,9 @@ no symbol lookup (faster)
2828
\fB\-o\fR <path>
2929
write output to specified file path, instead of stderr
3030
.TP
31+
\fB\-s\fR <SIG>
32+
enable on\-demand logging when signalled SIG signal
33+
.TP
3134
\fB\-t\fR <tools>
3235
analysis tools to use (default "leak")
3336
.TP

src/huapi.h src/heapusage.h

+3-7
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,14 @@
11
/*
2-
* huapi.h
2+
* heapusage.h
33
*
4-
* Copyright (C) 2021 Kristofer Berggren
4+
* Copyright (C) 2024 Kristofer Berggren
55
* All rights reserved.
66
*
77
* heapusage is distributed under the BSD 3-Clause license, see LICENSE for details.
88
*
99
*/
1010

11-
#ifndef _HUAPI_H_
12-
#define _HUAPI_H_
13-
11+
#pragma once
1412

1513
/* ----------- Global Function Prototypes ------------------------ */
1614

@@ -23,5 +21,3 @@ void hu_report(void);
2321
#ifdef __cplusplus
2422
}
2523
#endif
26-
27-
#endif /* _HUAPI_H_ */

src/huapi.cpp

-22
This file was deleted.

src/hulog.cpp

+8-38
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
/*
22
* hulog.cpp
33
*
4-
* Copyright (C) 2017-2022 Kristofer Berggren
4+
* Copyright (C) 2017-2024 Kristofer Berggren
55
* All rights reserved.
66
*
77
* heapusage is distributed under the BSD 3-Clause license, see LICENSE for details.
@@ -20,7 +20,6 @@
2020
#include <stdlib.h>
2121
#include <string.h>
2222
#include <unistd.h>
23-
#include <stdarg.h>
2423

2524
#include <map>
2625
#include <set>
@@ -386,31 +385,7 @@ void hu_sig_handler(int sig, siginfo_t* si, void* /*ucontext*/)
386385
exit(EXIT_FAILURE);
387386
}
388387

389-
void log_message(const char *format, ...)
390-
{
391-
va_list args;
392-
393-
FILE *f = NULL;
394-
if (hu_log_file)
395-
{
396-
f = fopen(hu_log_file, "a");
397-
}
398-
399-
if (!f)
400-
{
401-
return;
402-
}
403-
404-
fprintf(f, "==%d== MESSAGE: ", pid);
405-
406-
va_start(args, format);
407-
vfprintf(f, format, args);
408-
va_end(args);
409-
410-
fclose(f);
411-
}
412-
413-
void log_summary()
388+
void log_summary(bool ondemand)
414389
{
415390
FILE *f = NULL;
416391
if (hu_log_file)
@@ -455,6 +430,12 @@ void log_summary()
455430
allocations_by_size.insert(it->second);
456431
}
457432

433+
/* Indicate in case an on-demand report */
434+
if (ondemand)
435+
{
436+
fprintf(f, "==%d== ON DEMAND REPORT\n", pid);
437+
}
438+
458439
/* Output heap summary */
459440
fprintf(f, "==%d== HEAP SUMMARY:\n", pid);
460441
fprintf(f, "==%d== in use at exit: %llu bytes in %llu blocks\n",
@@ -490,17 +471,6 @@ void log_summary()
490471
fclose(f);
491472
}
492473

493-
void log_summary_safe()
494-
{
495-
hu_set_bypass(true);
496-
log_enable(0);
497-
498-
log_summary();
499-
500-
log_enable(1);
501-
hu_set_bypass(false);
502-
}
503-
504474
void hu_log_remove_freed_allocation(void* ptr)
505475
{
506476
if (!hu_log_free)

src/hulog.h

+4-4
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,15 @@
11
/*
22
* hulog.h
33
*
4-
* Copyright (C) 2017-2021 Kristofer Berggren
4+
* Copyright (C) 2017-2024 Kristofer Berggren
55
* All rights reserved.
66
*
77
* heapusage is distributed under the BSD 3-Clause license, see LICENSE for details.
88
*
99
*/
1010

11+
#pragma once
12+
1113
/* ----------- Includes ------------------------------------------ */
1214
#include <signal.h>
1315

@@ -24,7 +26,5 @@ void log_enable(int flag);
2426
void log_event(int event, void* ptr, size_t size);
2527
void log_invalid_access(void* ptr);
2628
void hu_sig_handler(int sig, siginfo_t* si, void* /*ucontext*/);
27-
void log_message(const char *format, ...);
28-
void log_summary();
29-
void log_summary_safe();
29+
void log_summary(bool ondemand);
3030
void hu_log_remove_freed_allocation(void* ptr);

0 commit comments

Comments
 (0)