Is there any option for enabling no memory management in gcc while compiling?
问题:
回答1:
Main points on using Valgrind while debugging C code compiled with GCC:
Compile your code using -O0. In some relatively rare cases (e.g. inline assembly) you may need -O1. Never use higher optimisation levels. The compiler will mangle your code so much that it can make your life impossible. Variables can disappear completely, functions can go mysteriously away as they get inlined, loops become unrolled and so on. Basically with anything other than -O0 you run the risk that the executable code will bear little resemblance to your source code.
Use the -g GCC option to add debugging symbols to your code and DO NOT strip the executables. Much like any other debugger, valgrind will produce infinitely more useful output with debugging symbols available. They will help valgrind match memory addresses to specific files and line numbers in your code which is invaluable.
To track memory leaks and many other problems I suggest running your program with:
valgrind --log-file=valgrind.log --leak-check=full --track-origins=yes --show-reachable=yes ./program
Then look in the valgrind.log file for any problems found.
EDIT:
About the valgrind options I suggested:
--log-file= tells valgrind to send its output to a file, which I believe can make things easier when you are debugging programs with output to the console, or when there are lots of issues found.
--leak-check=full tells valgrind to tell you details about each leaked memory block.
--track-origins=yes tells valgrind to find out where uninitialised values came from. It does not have anything to do with memory leaks, although it can help deal with other issues. It makes your program slower, though, so you might want to remove this option and add it only when you are tracking uninitialised values.
--show-reachable=yes tells valgrind to output memory blocks that have been allocated and not freed, even if there are still pointers to them at program exit. These blocks are not technically lost/leaked, since you still have pointers to them. Still, they can a) indicate a logic problem in your program (e.g. a list that grows indefinitely) b) they can and will become memory leaks if your main() becomes integrated as a function in another larger program. It would be best that there are no such issues left.
There is a --track-fds=yes option that can help find leaking file descriptors instead of just memory.
Some programmers advocate against freeing memory or closing file descriptors at program end, since the OS does that anyway. While there is a performance and code size advantage there, IMHO this should only be done by experienced programmers only, and it should be done by removing said code for the production release, rather than just never writing it. Otherwise, this encourages bad coding practices that should not be allowed.
EDIT 2:
One important hint: If valgrind indicates a problem in your code, it is most probably right, even if your program does not crash. Some "minor" errors (e.g. reading one byte past the end of a buffer) can remain unseen, depending on structure alignment, memory allocator behaviour, platform, compiler version and flags, or the phase of the moon. Code with such issues might just break if you change compiler, libc, platform or bitness (e.g. go from 64 to 32 bit).
回答2:
Compile your program without optimization, and with debug symbols for best results (-O0 -g
).
Now run an instance of your program, utilizing as much functionality as possible, wrapping the call like so:
valgrind ./myprog my prog args
I often find it useful to pass the following flags to valgrind:
valgrind --leak-check=full --track-fds=yes --track-origins=yes --malloc-fill=0x80 --free-fill=0x7f ./myprog my prog args
However valgrind will provide much prompting to assist you regarding what parameters to pass, should it find stuff on less thorough passes.