I am trying to view the annotated source using $ valgrind --tool=callgrind ./myProgram
followed by $ kcachegrind
using Ubuntu 12.04 (and I'm having the same problem with $ qcachegrind
using Mac OSX).
The C++ script myProgram.cpp
makes calls to functions that live in a .hpp
file (via #include "../include/myHeader.hpp"
, etc.). I compile myProgram.cpp
like this:
g++ -g -o myProgram myProgram.o -l<some third party lib>
where I don't care about viewing annotated source for that third party lib.
What I would like to see is annotated source for the functions in myHeader.hpp
and for myProgram.cpp
.
Instead, I see kcachegrind's Flat Profile window with a list of all the functions that get called, including the functions in myHeader.hpp
- this is great. Now, kcachegrind reports the location of functions from myHeader.hpp
as being from myProgram
- this is odd. And finally, when I select any function from the Flat Profile window and request to see Source Code, I am met with:
There is no source available for the following function
<name of the selected function>
This is because no debug information is present.
Recompile the source and redo the profile run.
The function is located in the ELF object:
<some location...>
What I've tried:
added the directory holding myHeader.hpp
to the Annotations list using kcachegrind's GUI.
compiled using -O0 to remove compiler optimizations
I'm answering my own question thanks to user n.m. - I discovered this while running a simplified example. The problem was with my compilation instruction, I was compiling to an object file with -g
rather than compiling to an executable with -g
.
Here's a working example for how to get kcachegrind to show annotated source:
main.cpp
lives in directory someDirectory/example
// main.cpp
#include <iostream>
#include <math.h>
#include "../include/header.hpp"
using namespace std;
int main() {
double a=1.0; double b=4.0;
double tol = 1E-10;
double zero = -99;
if (sin(a)*sin(b) < 0 && (b-a) >= tol)
zero = bisect_sine(a,b,tol);
cout << zero << endl;
return 0;
}
Header file header.hpp
lives in someDirectory/include
// header.hpp
#include <math.h>
#include <iostream>
using namespace std;
double bisect_sine(double a, double b, double tol) {
double c;
int step = 0; int maxsteps = 100;
while (step < maxsteps) {
c = (a+b)/2.0;
if (sin(c) == 0 || (b-a)/2 < tol)
return c;
if (sin(a)*sin(c) >= 0)
a = c;
else
b = c;
step+=1;
}
}
Makefile
# Makefile
CXX = g++
main:
$(CXX) -g -o main main.cpp
chmod 700 main
clean:
rm main
After all of this, simply run make
(yielding the executable main
that was compiled with debugging -g
), followed by valgrind --tool=callgrind ./main
. This will produce the expected callgrind.out.<PID>
file, which can be read by kcachegrind. Source annotation will then be available for the main()
function of main.cpp as well as for bisect_sine()
from the header file.
So, this turned out to be a compilation issue. If I understood more about compilation into executables, object files, shared objects, yada yada yada, I would not have gotten into this mess.