3

When I run a simple Valgrind command, such as...

valgrind --leak-check=yes ./my_program

...the error output Valgrind produces shows where in the source code a memory allocation was made and where it was freed. How is Valgrind able to do this? How I could I do this myself, in the code of the program? If it helps, the CFLAGS parameters defined in my GCC makefile for the compilation are:

CFLAGS=-c -Wall -Wextra -Wno-unused-parameter -Wno-unused-variable -g -Og -std=c11 -pedantic
Theo d'Or
  • 783
  • 1
  • 4
  • 17

2 Answers2

3

the error output Valgrind produces shows where in the source code a memory allocation was made and where it was freed. How is Valgrind able to do this?

When you use valgrind, you do not launch your program directly. Instead, valgrind does it, in an environment and by means that permit it to do its monitoring in the first place. This includes, but is not limited to, substituting its own allocation functions for the standard library's normal implementations. It is these alternative allocation functions that give Valgrind the means to track the locations in the binary where allocations and frees occur.

The information necessary to associate source line numbers with specific instructions in the compiled binary is part of the debug information included in the binary when you compile with the -g option. If you omit the -g you will find that Valgrind's output is less informative about the location of the error.

How I could I do this myself, in the code of the program?

You also can provide your own malloc etc. and free functions. You can cause them to be used throughout your program instead of the standard library's versions, though the details may depend in part on your C implementation. Doing this correctly is non-trivial and details are system-dependent.

Means by which these functions can identify the point from which they are called is even more non-trivial and system dependent. The C language does not define any kind of introspective feature such as this would require, so you would need to provide that yourself.

Standard C also does not define any way that a program could access debug information from its own binary, nor even any reliable way even to locate its own binary, nor, for that matter, "debug information". Valgrind has a distinct advantage over the program itself in this area: since valgrind launches the program, valgrind is in a position to know what binary it is launching.

Overall, then, the answer is that if you have to ask the question in the first place then you probably are not equipped to do what you ask at all. You should instead look for an existing tool that does close enough to what you want (maybe valgrind itself), or change your requirements. In particular, you should consider whether the preprocessor-based mechanism described in @ryyker's answer provides a means to get close enough to what you have in mind.

John Bollinger
  • 160,171
  • 8
  • 81
  • 157
2

...access line number of memory allocation in compiled C program, how I can I do the same?

Predefined macros, such as __FILE__, __FUNCTION__ and __LINE__can be used in C source to output information about where something is happening. The number and variety of macros are somewhat environment dependent. __FUNCTION__ for example is an extension, and is not among the predefined macros specified by the standard as pointed out in the comments. You can read about GCC macro usage and extensions here. (See links above for additional hints on usage.)

In this example these macros are used to show In which file, function and on which line # the event occurs:

char buf[100];
sprintf(buf, "%p (%s() %s() line# %d)\n", malloc(10), __FILE__, __FUNCTION__, __LINE__);
printf(buf);//(Or more likely usage, write to a log file)

Note, this example has no error checking/handling such as checking the return value for malloc(), which is always a good idea.

ryyker
  • 22,849
  • 3
  • 43
  • 87
  • To add, frameworks like valgrind adds hooks to the existing library functions and uses these macros and more to insert these info, then uses them during debugging. – Sourav Ghosh Jan 16 '20 at 13:24
  • 1
    I am not too confident of the Valgrind (never looked at the source code), but this is usually the strategy. I did this for one of my project. If you know for sure valgrinds does this, feel free to add, otherwise, let it be a hint in a comment. – Sourav Ghosh Jan 16 '20 at 13:28