kcachegrind: there is no source available for the following function
Asked Answered
L

1

6

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

Lineberry answered 10/4, 2014 at 17:49 Comment(1)
Provide a self-contained example that can be copied, pasted, compiled and ran through valgrind. We cannot possibly check what's wrong with <some function> at <some location>.Barefoot
L
7

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.

Lineberry answered 13/4, 2014 at 22:5 Comment(1)
This was helpful, thanks!. Some improvements: You should either add return c at the end of bisect_sine(...) or specify the return type as void. Also, to make this more of a minimal example, the header.hpp can be moved to the same folder of main.cpp and make the include "cleaner".Alegre

© 2022 - 2024 — McMap. All rights reserved.