Discussion:
gcno file doesn't include uncalled member functions?
Michael Morrell
2008-05-06 18:58:09 UTC
Permalink
It seems that the gcno file produced by gcc when the coverage flags are
given
doesn't include data for a member function defined in a header, but not
called. It seems that it is optimizing away the uncalled member function
even though I am using -O0. Is there another option that I should use?

Here is my test case:

========= Rect.h ===============
class Rect {
public:
Rect(int x, int y) { m_x = x; m_y = y; }
int x() const { return m_x; }
int y() const { return m_y; }

private:
int m_x;
int m_y;
};
================================

======== Main.cpp ==============
include <stdio.h>
#include "Rect.h"

int main()
{
Rect* rect = new Rect(3, 5);

printf("x: %d\n", rect->x());
//printf("y: %d\n", rect->y());
return 0;
}
================================

And I compile this using:
g++ -fprofile-arcs -ftest-coverage -O0 -o rect Main.cpp

With the above call to "rect->y" commented out, the generated Main.gcno
file only lists 2 functions from Rect.h: the constructor and the "x"
function.

Can anyone enlighten me on this behavior?

Thanks,

Michael


____________________________________________________________________________________
Be a better friend, newshound, and
know-it-all with Yahoo! Mobile. Try it now. http://mobile.yahoo.com/;_ylt=Ahu06i62sR8HDtDypao8Wcj9tAcJ
John Love-Jensen
2008-05-06 19:20:38 UTC
Permalink
Hi Michael,

Keep in mind that profiling -O0 produces not-useful results for performance
profiling. (It may produce useful results for other purposes. Such as code
exercise coverage.)

I tweaked your compile flags:

# g++ -fprofile-arcs \
-ftest-coverage \
-fno-default-inline \
-fkeep-inline-functions \
-O0 -o rect main.cpp

# ./rect

# gcov -l -f main.gcda | c++filt -n

Hey, that's useful info! I've never used gcov before.

HTH,
--Eljay
Michael Morrell
2008-05-07 00:34:45 UTC
Permalink
Thanks for the help.

Can you elaborate on your comment about -O0 producing not-useful results?
I am only using it in the context of compiling for coverage and was trying
to avoid any gotchas (I have seen gcc produce incorrect code when using
the coverage options with optimization).

I'm confused also as to why the extra options you used were necessary.
From the man page, there are two paragraphs about -fno-default-inline:

-fno-default-inline
Do not assume inline for functions defined inside a class scope.
Note that these functions will have linkage like inline functions;
they just won't be inlined by default.

-fno-default-inline
Do not make member functions inline by default merely because they
are defined inside the class scope (C++ only). Otherwise, when you
specify -O, member functions defined inside class scope are
compiled inline by default; i.e., you don't need to add inline in
front of the member function name.

I'm not sure which one reflects reality. The second suggests that the
option only makes a difference when using -O (i.e., member functions
defined inside class scope shouldn't be treated as inline with -O0).

And, for -fkeep-inline-functions:

-fkeep-inline-functions
In C, emit "static" functions that are declared "inline" into the
object file, even if the function has been inlined into all of its
callers. This switch does not affect functions using the "extern
inline" extension in GNU C. In C++, emit any and all inline
functions into the object file.

If, at -O0, the member functions aren't considered inline functions, then
this option should have no effect, but perhaps the 2nd paragraph about
-fno-default-inline is incorrect and the default behavior for these member
functions is to inline them even at -O0. If so, I question whether that
makes sense. Since it also affects .gcno output, perhaps -fprofile-arcs
should imply these other two options.

Finally, while I haven't been able to come up with a nice test case to
post here, another anomaly I discovered is that the the .gcno file will
list a line as instrumented but doesn't list the corresponding function,
making tools like gcov or lcov think the line is part of a different
function. Using the new options seems to make this go away, so I guess
it's not that important, but I thought I'd mention it to see if anyone
else ever saw something like that or thinks it should be fixed.

Perhaps gcov usage is very rare out there.

Michael
Post by John Love-Jensen
Hi Michael,
Keep in mind that profiling -O0 produces not-useful results for performance
profiling. (It may produce useful results for other purposes. Such as code
exercise coverage.)
# g++ -fprofile-arcs \
-ftest-coverage \
-fno-default-inline \
-fkeep-inline-functions \
-O0 -o rect main.cpp
# ./rect
# gcov -l -f main.gcda | c++filt -n
Hey, that's useful info! I've never used gcov before.
HTH,
--Eljay
____________________________________________________________________________________
Be a better friend, newshound, and
know-it-all with Yahoo! Mobile. Try it now. http://mobile.yahoo.com/;_ylt=Ahu06i62sR8HDtDypao8Wcj9tAcJ
John Love-Jensen
2008-05-07 11:47:57 UTC
Permalink
Hi Michael,
Post by Michael Morrell
Can you elaborate on your comment about -O0 producing not-useful results?
That's in the context of performance profiling.

I have seen performance profiling that indicated that 90% of the programs
time was spent in a routine that in the optimized build was much less than
1% of the time.

That specific case is exemplary of non-optimized builds in general. Hence
performance profiling for the non-optimized build is not interesting, since
time spent fine-tuning (or re-architecting) the non-performant non-optimized
code is not a useful effort.

In the context of coverage profiling, -O0 should be fine. Perhaps even
preferred.

The rest of your message is a bit out of my knowledge, so hopefully someone
else addresses your other inquiries.

Sincerely,
--Eljay

Loading...