Assuming you are using GCC, you can get this kind of information from the GCC manual
http://gcc.gnu.org/onlinedocs/gcc/Debugging-Options.html#Debugging-Options
-p
Generate extra code to write profile information suitable for the analysis program
prof. You must use this option when compiling the source files you want data about, and you must also use it when linking.
-g
Answer from hugomg on Stack OverflowProduce debugging information in the operating system's native format (stabs, COFF, XCOFF, or DWARF 2). GDB can work with this debugging information.
On most systems that use stabs format, -g enables use of extra debugging information that only GDB can use; this extra information makes debugging work better in GDB but will probably make other debuggers crash or refuse to read the program. If you want to control for certain whether to generate the extra information, use -gstabs+, -gstabs, -gxcoff+, -gxcoff, or -gvms (see below).
GCC allows you to use -g with -O. The shortcuts taken by optimized code may occasionally produce surprising results: some variables you declared may not exist at all; flow of control may briefly move where you did not expect it; some statements may not be executed because they compute constant results or their values were already at hand; some statements may execute in different places because they were moved out of loops.
Nevertheless it proves possible to debug optimized output. This makes it reasonable to use the optimizer for programs that might have bugs.
Assuming you are using GCC, you can get this kind of information from the GCC manual
http://gcc.gnu.org/onlinedocs/gcc/Debugging-Options.html#Debugging-Options
-p
Generate extra code to write profile information suitable for the analysis program
prof. You must use this option when compiling the source files you want data about, and you must also use it when linking.
-g
Produce debugging information in the operating system's native format (stabs, COFF, XCOFF, or DWARF 2). GDB can work with this debugging information.
On most systems that use stabs format, -g enables use of extra debugging information that only GDB can use; this extra information makes debugging work better in GDB but will probably make other debuggers crash or refuse to read the program. If you want to control for certain whether to generate the extra information, use -gstabs+, -gstabs, -gxcoff+, -gxcoff, or -gvms (see below).
GCC allows you to use -g with -O. The shortcuts taken by optimized code may occasionally produce surprising results: some variables you declared may not exist at all; flow of control may briefly move where you did not expect it; some statements may not be executed because they compute constant results or their values were already at hand; some statements may execute in different places because they were moved out of loops.
Nevertheless it proves possible to debug optimized output. This makes it reasonable to use the optimizer for programs that might have bugs.
-p provides information for prof, and -pg provides information for gprof.
Let's look at the latter.
Here's an explanation of how gprof works,
but let me condense it here.
When a routine B is compiled with -pg, some code is inserted at the routine's entry point that looks up which routine is calling it, say A.
Then it increments a counter saying that A called B.
Then when the code is executed, two things are happening. The first is that those counters are being incremented. The second is that timer interrupts are occurring, and there is a counter for each routine, saying how many of those interrupts happened when the PC was in the routine.
The timer interrupts happen at a certain rate, like 100 times per second. Then if, for example, 676 interrupts occurred in a routine, you can tell that its "self time" was about 6.76 seconds, spread over all the calls to it.
What the call counts allow you to do is add them up to tell how many times a routine was called, so you can divide that into its total self time to estimate how much self time per call. Then from that you can start to estimate "cumulative time". That's the time spent in a routine, plus time spent in the routines that it calls, and so on down to the bottom of the call tree.
This is all interesting technology, from 1982, but if your goal is to find ways to speed up your program, it has a lot of issues.
Videos
my professor advised us to use these flags when compiling :
-Wall -Weffc++ -Wextra -Wsign-conversion
and I wanted to know your thoughts on the use of flags and static analyzers, do you actually use them or does it become annoying ?
That's kind of right, but incomplete. -g requests that the compiler and linker generate and retain source-level debugging/symbol information in the executable itself.
If...
- the program happens to later crash and produce a core file (which suggests some problem in the actual code), or
- a deliberate OS command forced it to core (e.g.
kill -SIGQUITpid), or - the program calls a function that dumps core (e.g.
abort)
...- none of which are actually caused by the use of -g - then the debugger will know how to read that "-g" symbol information from the executable and cross-reference it with the core. This means you can see the proper names of variables and functions in your stack frames, get line numbers and see the source as you step around in the executable.
That debug information is useful whenever debugging - whether you started with a core or just the executable alone. It even helps produce better output from commands like pstack.
Note that your environment may have other settings to control whether cores are generated (they can be big, and there's no general way to know if/when they can be removed, so they're not always wanted). For example, on UNIX/LINUX shells it's often ulimit -c.
You may also be interested to read about DWARF Wikipedia - a commonly used debugging information format for encoding the embedded debug/symbol information in executable/library objects (e.g. on UNIX and Linux).
UPDATE per Victor's request in comments...
Symbol information lists identifiers from the source code (usually only after any name mangling needed), the (virtual) memory addresses/offsets at which they'll be loaded in the process memory, the type (e.g. data vs. code). For example...
$ cat ok.cc
int g_my_num;
namespace NS { int ns_my_num = 2; }
int f() { return g_my_num + NS::ns_my_num; }
int main() { return f(); }
$ g++ -g ok.cc -o ok # compile ok executable with symbol info
$ nm ok # show mangled identifiers
00000000004017c8 d _DYNAMIC
0000000000401960 d _GLOBAL_OFFSET_TABLE_
0000000000400478 R _IO_stdin_used
w _ITM_deregisterTMCloneTable
w _ITM_registerTMCloneTable
w _Jv_RegisterClasses
000000000040037c T _Z1fv # this is f()
0000000000401798 D _ZN2NS9ns_my_numE # this is NS::ns_my_num
00000000004017a8 d __CTOR_END__
00000000004017a0 d __CTOR_LIST__
00000000004017b8 d __DTOR_END__
00000000004017b0 d __DTOR_LIST__
0000000000400540 r __FRAME_END__
00000000004017c0 d __JCR_END__
00000000004017c0 d __JCR_LIST__
00000000004017c8 d __TMC_END__
00000000004017c8 d __TMC_LIST__
0000000000401980 A __bss_start
0000000000401788 D __data_start
0000000000400440 t __do_global_ctors_aux
00000000004002e0 t __do_global_dtors_aux
0000000000401790 d __dso_handle
0000000000000000 a __fini_array_end
0000000000000000 a __fini_array_start
w __gmon_start__
0000000000000000 a __init_array_end
0000000000000000 a __init_array_start
00000000004003a0 T __libc_csu_fini
00000000004003b0 T __libc_csu_init
U __libc_start_main
0000000000000000 a __preinit_array_end
0000000000000000 a __preinit_array_start
0000000000401980 A _edata
0000000000401994 A _end
0000000000400494 T _fini
000000000040047c T _init
0000000000400220 T _start
000000000040024c t call_gmon_start
0000000000401980 b completed.6118
0000000000401788 W data_start
0000000000400270 t deregister_tm_clones
0000000000401988 b dtor_idx.6120
0000000000401994 A end
0000000000400350 t frame_dummy
0000000000401990 B g_my_num # our global g_my_num
0000000000400390 T main # the int main() function
00000000004002a0 t register_tm_clones
$ nm ok | c++filt # c++filt "unmangles" identifiers...
00000000004017c8 d _DYNAMIC
0000000000401960 d _GLOBAL_OFFSET_TABLE_
0000000000400478 R _IO_stdin_used
w _ITM_deregisterTMCloneTable
w _ITM_registerTMCloneTable
w _Jv_RegisterClasses
000000000040037c T f()
0000000000401798 D NS::ns_my_num
00000000004017a8 d __CTOR_END__
00000000004017a0 d __CTOR_LIST__
00000000004017b8 d __DTOR_END__
00000000004017b0 d __DTOR_LIST__
0000000000400540 r __FRAME_END__
00000000004017c0 d __JCR_END__
00000000004017c0 d __JCR_LIST__
00000000004017c8 d __TMC_END__
00000000004017c8 d __TMC_LIST__
0000000000401980 A __bss_start
0000000000401788 D __data_start
0000000000400440 t __do_global_ctors_aux
00000000004002e0 t __do_global_dtors_aux
0000000000401790 d __dso_handle
0000000000000000 a __fini_array_end
0000000000000000 a __fini_array_start
w __gmon_start__
0000000000000000 a __init_array_end
0000000000000000 a __init_array_start
00000000004003a0 T __libc_csu_fini
00000000004003b0 T __libc_csu_init
U __libc_start_main
0000000000000000 a __preinit_array_end
0000000000000000 a __preinit_array_start
0000000000401980 A _edata
0000000000401994 A _end
0000000000400494 T _fini
000000000040047c T _init
0000000000400220 T _start
000000000040024c t call_gmon_start
0000000000401980 b completed.6118
0000000000401788 W data_start
0000000000400270 t deregister_tm_clones
0000000000401988 b dtor_idx.6120
0000000000401994 A end
0000000000400350 t frame_dummy
0000000000401990 B g_my_num
0000000000400390 T main
00000000004002a0 t register_tm_clones
Notes:
- our functions
f()andmain()are typeT(which stands for "TEXT" - used for read-only non-zero memory content whether it's actually text or other data or executable code), g_my_numisBbeing a global with implicitly zero-ed out memory, whileNS::ns_my_numisDas the executable has to explicitly provide the value2to occupy that memory.
The man/info-page for nm documents these things further....
The -g flag tells the compiler to generate debugging information. It has no impact on whether or not a core file will be generated. On most unix-like systems, that can be setup using the ulimit command.
Hi,
I'm a beginner, barely scratching the surface of C at the moment. Question is, what flags do I choose for compilation? There are some "basic" like -Wall, -W, -pedantic, -ansi, -std=. GCC documentation has a ton of different flags.
Should I learn Make or CMake early to avoid retyping flags every time to compile my source files?Any help, advice are greatly appreciated.
Edit: thank you, guys. Lots of useful and interesting information. You're awesome!