Bug 24550 - incorrect gcov code coverage output in 4.0 and 4.1
Summary: incorrect gcov code coverage output in 4.0 and 4.1
Status: RESOLVED DUPLICATE of bug 15369
Alias: None
Product: gcc
Classification: Unclassified
Component: c++ (show other bugs)
Version: 4.1.0
: P2 major
Target Milestone: ---
Assignee: Not yet assigned to anyone
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2005-10-27 00:57 UTC by Martin Reddy
Modified: 2005-10-27 01:36 UTC (History)
2 users (show)

See Also:
Host: x86_64-redhat-linux-gnu
Target: x86_64-redhat-linux-gnu
Build: x86_64-redhat-linux-gnu
Known to work:
Known to fail:
Last reconfirmed:


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Martin Reddy 2005-10-27 00:57:18 UTC
I have come across a number of cases where gcov 4.0 and beyond produces incorrect output, causing false reporting of code coverage. For example, lines beyond the end of the source file are marked as executable with zero coverage, and some lines are marked with zero coverage even though they are directly after a simple statement that was marked as being executed. These problems are consistently reproducible on our platforms here.

I have confirmed that these problems did *not* occur in gcov 3.3.2, 3.3.3, or 3.4.3. I have further confirmed that they *do* occur in gcov 4.0.1 and gcov 4.1.0 (20051001). See below for more details on these versions.

Here's a simple test case that demonstrates the two problems I list above:

 % g++ -fprofile-arcs -ftest-coverage -c mytest.cpp -o mytest.o
 % g++ -fprofile-arcs -ftest-coverage mytest.o -o mytest
 % ./mytest
 % gcov mytest.cpp ; cat mytest.cpp.gcov

-------------- mytest.cpp ----------------
#include <string>

// this global string causes gcov to think there's executable lines
// beyond the end of the file, and that they have not been executed
std::string globalVar = "";

std::string
doSomething()
{
    // instantiating this string and calling a method on it causes the
    // 'return' line to be marked as having never been executed
    std::string localVar;
    localVar.size();
    return localVar;
}

int
main(int, char **)
{
    doSomething();
    return 0;
}
------------------------------------------

Under gcc/gcov 4.0.1 and 4.1.0 this produces:

        -:    0:Source:mytest.cpp
        -:    0:Graph:mytest.gcno
        -:    0:Data:mytest.gcda
        -:    0:Runs:1
        -:    0:Programs:1
        -:    1:#include <string>
        -:    2:
        -:    3:// this global string causes gcov to think there's executable lines
        -:    4:// beyond the end of the file
        1:    5:std::string globalVar = "";
        -:    6:
        -:    7:std::string
        1:    8:doSomething()
        -:    9:{
        -:   10:    // instantiating this string and calling a method on it causes the
        -:   11:    // 'return' line to be marked as executable but with zero coverage
        1:   12:    std::string localVar;
        1:   13:    localVar.size();
    #####:   14:    return localVar;
        -:   15:}
        -:   16:
        -:   17:int
        1:   18:main(int, char **)
        -:   19:{
        1:   20:    doSomething();
        1:   21:    return 0;
        1:   22:}
        1:   23:/*EOF*/
    #####:   24:/*EOF*/

Note that the lines marked with "#####" mean that gcov thought that these were executable lines of code, and that they where not actually executed. For comparison, the same test case compiled using gcc/gcov 3.3.3 (20040412) generates what I believe is more correct:

        -:    0:Source:mytest.cpp
        -:    0:Object:mytest.bb
        -:    1:#include <string>
        -:    2:
        -:    3:// this global string causes gcov to think there's executable lines
        -:    4:// beyond the end of the file
        4:    5:std::string globalVar = "";
        -:    6:
        -:    7:std::string
        -:    8:doSomething()
        1:    9:{
        -:   10:    // instantiating this string and calling a method on it causes the
        -:   11:    // 'return' line to be marked as executable but with zero coverage
        1:   12:    std::string localVar;
        1:   13:    localVar.size();
        1:   14:    return localVar;
        -:   15:}
        -:   16:
        -:   17:int
        -:   18:main(int, char **)
        1:   19:{
        1:   20:    doSomething();
        1:   21:    return 0;
        1:   22:}

Here's the output of gcc -v for both of the 4.x versions that I have confirmed these problems with:

Using built-in specs.
Target: x86_64-redhat-linux-gnu
Configured with: ../gcc-4.0.1/configure x86_64-redhat-linux-gnu --prefix=/pixar/d2/sets/tools-30 --exec-prefix=/pixar/d2/sets/tools-30 --bindir=/pixar/d2/sets/tools-30/bin --sbindir=/pixar/d2/sets/tools-30/sbin --sysconfdir=/pixar/d2/sets/tools-30/etc --datadir=/pixar/d2/sets/tools-30/share --includedir=/pixar/d2/sets/tools-30/include --libdir=/pixar/d2/sets/tools-30/lib --libexecdir=/pixar/d2/sets/tools-30/libexec --localstatedir=/pixar/d2/sets/tools-30/var --sharedstatedir=/pixar/d2/sets/tools-30/com --mandir=/pixar/d2/sets/tools-30/man --infodir=/pixar/d2/sets/tools-30/info --enable-version-specific-runtime-libs --enable-languages=c++,objc,f95 --enable-threads=posix --enable-shared
Thread model: posix
gcc version 4.0.1

Using built-in specs.
Target: x86_64-unknown-linux-gnu
Configured with: ../configure --prefix=/data/gcc/gcc-4.1-20051001 --enable-languages=c,c++,objc,obj-c++ --enable-version-specific-runtime-libs
Thread model: posix
gcc version 4.1.0 20051001 (experimental)


I suspect that this is something to do with allocating objects on the stack (std::string in the example above, though I've tried this with other stl container classes as well as other non-stl classes). For example, in the case of coverage being produced beyond the end of the file for gcov 4.x, if I supply the -b argument to gcov I get this at the end:

        1:   22:}
function _GLOBAL__I_globalVar called 1 returned 100% blocks executed 100%
        1:   23:/*EOF*/
call    0 returned 100%
function _GLOBAL__D_globalVar called 0 returned 0% blocks executed 0%
    #####:   24:/*EOF*/
call    0 never executed

Also, in the test case above, if I change the return value of doSomething() to be an int instead of a std::string then the problem does not occur.

As another interesting datapoint, the above information is for running on a Fedora Core 2 machine, but I get similar behavior using Apple's 4.0.0 compiler that they ship with OSX 10.4 (Tiger) - However, in that case the /*EOF*/ coverage error on line 24 doe not occur. Only the one on line 14 occurs. Perhaps that helps to isolate some part of this problem.

Please let me know if there is any more information that I can provide you to help reproduce this problem. We are actively using gcov to quantify the code coverage of our automated tests, so we'd love to see this problem get fixed and I'm happy to help out as much as I can.

Cheers,

Martin.
Comment 1 Andrew Pinski 2005-10-27 01:02:39 UTC
    // instantiating this string and calling a method on it causes the
    // 'return' line to be marked as having never been executed
This is PR 12076, the problem is more in the front-end for that one, it is not a regression though.
Comment 2 Andrew Pinski 2005-10-27 01:07:21 UTC
And the EOF issue is also a front-end issue too:
(static destructors for t.cc) ()
{
<bb 0>:
  [t.cc : 24] __static_initialization_and_destruction_0 (0, 65535);
  [t.cc : 24] return;


There might be antoher bug about this too, I have to look.
Comment 3 Andrew Pinski 2005-10-27 01:10:04 UTC
(In reply to comment #2)
> There might be antoher bug about this too, I have to look.

And there is, PR 15369.

Since both of these issues have been filed already, I am going to close this as a dup of last one.

*** This bug has been marked as a duplicate of 15369 ***
Comment 4 Martin Reddy 2005-10-27 01:36:18 UTC
Thanks for the bugdb digging Andrew. I did do some searching to see if these problems were reported, but didn't catch those reports. Sorry 'bout that.

PR 12076 does sound like a dupe, and the alternate behavior just suggested by Joe would be just fine.

Looks like the last word on PR 15369 was that there was a workaround for the case submitted there about adding breakpoints within a debugger, though in this case there is no workaround - the code coverage values will be incorrect.