memdetect
A shell script to compile your C file or project with a wrapper of malloc() and free(), which will help you understand your memory-management and debug better. P.S. It also fails them!
Info:
Platforms:
Enviroment:
Output file:
Setup:
Installation:
This program is made by a single shell executable so it doesn't need proper installation, to be able to run it just clone this repository and you're ready to test
git clone [email protected]:XEDGit/memdetect.git
cd memdetect
./memdetect.sh
Adding memdetect to your $PATH:
You can add this program to your $PATH by adding this flag
./memdetect.sh --add-path
from now on you can just type memdetect
in your terminal from any folder in the system!
Makefile integration:
You can integrate this program with Makefile by executing this command in your Makefile path
echo >> ./Makefile '
mem:
/path/to/memdetect.sh /path/to/project $(GCC_FLAGS) # add memdetect flags here'
Another useful integration, if you want the freedom of executing with different flags everytime
echo >> ./Makefile '
mem:
/path/to/memdetect.sh /path/to/project $(GCC_FLAGS) $(1)'
Which can be executed with
make mem 1='-fail 2'
Run:
You can either run memdetect on files by specifying their name, or with a directory path. If you insert a directory path every .c file inside the directory is gonna be compiled, to exclude some sub-folder use the -e
flag
Usage:
./memdetect.sh { <directory_path> | <file> [<file1...>] } [<gcc_flags>] [optional flags]
Flags:
-
Compiling:
-
-fl
--flags
flag0 flag1...: Another way to specify flags to use when compiling with gcc -
-e
--exclude
folder_name: Specify a folder inside thedirectory_path
which gets excluded from compiling
-
-
Executing:
-a
--args
arg0 arg1...: Specify arguments to run with the executable
-
Fail (Use only one):
-
-fail
number: Specify which malloc call should fail (return 0), 1 will fail first malloc and so on -
-fail
all: Adding this flag will fail all the malloc calls -
-fail
loop start_from: Your code will be compiled and ran in a loop, failing the 1st malloc call on the 1st execution, the 2nd on the 2nd execution and so on. If you specify a number afterloop
it will start by failingstart_from
malloc and continue. This flag is really useful for debugging
-
-
Output:
-
-o
--output
filename: Sends all the output without terminal colors to the specified file -
-il
--include-lib
: Adding this flag will include in the output the library name from where the first shown function have been called -
-ie
--include-ext
: Adding this flag will include in the output the calls to malloc and free from outside your source files.
Watch out, some external functions will create confilct and crash your program if you intercept them, try to filter them out with-fo
-
-ix
--include-xmalloc
: Adding this flag will include in the output the calls to xmalloc and xrealloc -
-nr
--no-report
: Doesn't display the leaks report at the program exit -
-fi
--filter-in
arg0 arg1...: Show only results from memdetect output if substringarg
is found inside the output line -
-fo
--filter-out
arg0 arg1...: Filter out results from memdetect output if substringarg
is found inside the output line
-
-
Output files:
-p
--preserve
: Adding this flag will mantain the executable output files
-
Program settings:
-
-lb
--leaks-buff
size: Specify the size of the leaks report buffer, standard is 10000 (use only if the output tells you to) -
-h
--help
: Display help message -
--add-path
: adds memdetect executable to a $PATH of your choice
-
All the optional flags will be added to the gcc command in writing order
Examples:
Run with single file
./memdetect.sh ft_split.c
Run with multiple files
./memdetect.sh ft_split.c ft_strlen.c
Run with project folder
./memdetect.sh ..
Run with options
./memdetect.sh shell/ -lreadline -L~/.brew/opt/readline/lib -I~/.brew/opt/readline/include -fail loop --filter-out rl_ -e examples
Understanding the output:
Reference:
-
(MALLOC_WRAPPER)
:- for each malloc call, it is printed on the stdout, with the last two functions in the stack, the amount of bytes and the address allocated
-
(FREE_WRAPPER)
:- for each free call, it is printed on the stdout, with the last two functions in the stack and the address freed
-
(MALLOC_FAIL)
:- when a malloc call gets failed by the
-fail
flag it will be printed on the stdout with the last two functions in the stack
- when a malloc call gets failed by the
-
(MALLOC_ERROR)
:- This means the program didn't have enough buffer size for storing malloc calls, use the flag
--leaks-buff
ot-lb
with a bigger value than default (10000) to fix this
- This means the program didn't have enough buffer size for storing malloc calls, use the flag
After your program exits a leak report will be printed.
if you use exit() all the addresses which have a reference stored in the stack gets freed automatically, but the report will still include them
Example:
example.c:
#include <stdlib.h>
#include <string.h>
int main(void)
{
char *str1, *str2, *str3;
str1 = malloc(3);
str1[0] = 'e';
str1[1] = 'x';
str1[2] = '\0';
str2 = strdup(str1);
str3 = strdup(str2);
free(str2);
return (0);
}
Output:
# With memdetect in $PATH
xedgit@pc:~ $ memdetect example.c -fail 3
DYLD_INSERT_LIBRARIES=./fake_malloc.dylib ./malloc_debug:
(MALLOC_WRAPPER 1) start -> main allocated 3 bytes at 0x7fa643c03590
(MALLOC_WRAPPER 2) main -> strdup allocated 3 bytes at 0x7fa643c03850
(MALLOC_FAIL) main -> strdup malloc num 3 failed
(FREE_WRAPPER) start -> main free 0x7fa643c03850
(MALLOC_REPORT)
Malloc calls: 2
Free calls: 1
Free calls to 0x0: 0
Leaks at exit:
1) From main of size 3 at address 0x7fa643c03590 Content: "ex"
Total leaks: 1