Code coverage missing a branch if a function takes reference parameter - c++

I have a following function which takes a reference parameter:
#include <iostream>
class A { static void TestA(const int &y) };
void A::TestA(const int &y) { std::cout << y; }
int main()
{
A::TestA(2);
return 0;
}
In my (lcov) code coverage with google unit tests, it is saying missing a branch with TestA() function, and symbols list have a stack_chk_fail symbol added. If I change the function parameter to non-reference then coverage is 100%.
I am using g++ compiler.
Am I missing anything ?
Thanks

The compiler inlines Test into main (because that's what a good compiler does). However, it also has to create code for Test because it has external linkage. Effectively, the code for the function exists twice: Once inlined into main and once in the code for Test that the linker can link with other compilation units.
If your compiler is bad with code attribution (in the debug symbols) for inlined functions (hello MSVC?) then your profiler will give you exactly the result you see: Executing the program does not lead to coverage for Test because no piece of the binary that is executed (i.e. main) has any line attribution into Test.
Changing the parameter type may affect inlining, but it's more likely that it changes how debug symbols are generated.
To verify this, step through the program with a debugger, with a breakpoint in Test. If that breakpoint is not hit when running main, your coverage tool won't see coverage for that line either. Or, if you really want, look into the debug symbols manually to see which lines have attribution. In Visual Studio you can also look at the disassembly while debugging (it will show the associated code lines).
For the above reasons you will generally get more reliable coverage results if you do coverage runs with debug builds (where e.g. inlining won't happen).

Related

Linker removes unreferenced code

I'm currently working on a modular project and some of our systems won't work, I'll try to explain what we're trying to do.
We've got a main project that is extended by a number of modules (dlls), these modules can have bootstrapper code that will register itself before the main loop starts. It will register itself using our bootstrapping system, however the problem for us is that the modules will not register itself unless we specifically call a function from said modules. We think this is because the linker removes unreferenced code as part of optimizations (this also happens in debug mode).
The main function is set up as follows:
#include <bootstrap/bootstrapper.hpp>
#include <module/module.hpp>
int main()
{
// foo is an empty function in the module header file
foo(); // if I were to remove this empty function,
// the modules bootstrapping code will not execute
return fade::bootstrap::run();
}
without the foo() function the bootstrapping code doesn't get executed
void foo()
{
}
namespace
{
std::unique_ptr<game> game_;
FADE_BOOTSTRAP_MODULE(module_game) // registers itself to the bootstrapper
}
We've tried a number of things such as the linker options:
/INCLUDE
/OPT:NOREF
/EXPORT
But to no avail, either it gives us undefined symbol errors or it does nothing at all.
Is there anything we can do so that the unreferenced code doesn't get optimized away? We want to keep our project modular and cross platform so we'd rather not hardcode any solutions to our main function.

Conditional optimization in Visual Studio

I have a code like this:
void f()
{
//Some function I want to debug
g();
//More code
}
void g()
{
//A very slow function I want to have optimized for performance
//No debugging this code
}
Where f is whatever function in my code I want to debug and g is a function computationally intensive.
When I compile the code with Release configuration, both pieces of code get optimized and it all runs in a reasonable time, but when I compile with Debug configuration, then g takes way too long to execute as the compiler don't optimize the code to keep it debugger-friendly.
I don't need to deal with g from a debugging point of view and can not extract it into a pre-compiled module (it's under active development and need to keep it up to date). They are defined in different files.
Is there a way to tell Visual Studio to compile g for speed, while keeping f compiled using Debug configuration?
You can either move f into another compilation unit, e.g. another file or #pragma optimize. The latter is probably the better choice because it's harder to forget you set that up than changing the compilation settings on a particular file, which you would have to remember to go back and reset.
Or you could just profile in debug mode and see what's happening. As VS Premium and above include these tools that shouldn't be too hard, or you can use a third party tool. Profiling usually gives a really good idea of what's the true cause of any slowdown.

lcov woes: weird duplicate constructor marked as not covered & function not marked as covered, even though its lines have been executed

On my quest to learn more about automated testing by getting a small C++ test project up & running with 100% coverage, I've run into the following issue - even though all my actual lines of code and all the execution branches are covered by tests, lcov still reports two lines as untested (they only contain function definitions), as well as a "duplicate" constructor method that is supposedly untested even though it matches my "real" constructor (the only one ever defined & used) perfectly.
(Skip to EDIT for the minimal reproduction case)
If I generate the same coverage statistics (from the same exact source, .gcno & .gcda files) using the gcovr python script and pass the results to the Jenkins Cobertura plugin, it gives me 100% on all counts - lines, conditionals & methods.
Here's what I mean:
The Jenkins Cobertura Coverage page: http://gints.dyndns.info/heap_std_gcovr_jenkins_cobertura.html (everything at a 100%).
The same .gcda files processed using lcov: http://gints.dyndns.info/heap_std_lcov.html (two function definition lines marked as not executed even though lines within those functions are fully covered, as well as functions Hit = functions Total - 1).
The function statistics for that source file from lcov: http:// gints.dyndns.info/heap_std_lcov_func (shows two identical constructor definitions, both referring to the same line of code in the file, one of them marked hit 5 times, the other 0 times).
If I look at the intermediate lcov .info file: http://gints.dyndns.info/lcov_coverage_filtered.info.txt I see that there are two constructor definitions there too, both are supposed to be on the same line: FN:8,_ZN4BBOS8Heap_stdC1Ev & FN:8,_ZN4BBOS8Heap_stdC2Ev.
Oh, and don't mind the messiness around the .uic include / destructor, that's just a dirty way of dealing with What is the branch in the destructor reported by gcov? I happened to be trying out when I took those file snapshots.
Anyone have a suggestion on how to resolve this? Is there some "behind-the-scenes" magic the C++ compiler is doing here? (An extra copy of the constructor for special purposes that I should make sure to call from my tests, perhaps?) What about the regular function definition - how can the definition line be untested even though the body has been fully tested? Is this simply an issue with lcov? Any suggestions welcome - I'd like to understand why this is happening and if there's really some functionality that my tests are leaving uncovered and Cobertura is not complaining about ... or if not, how do I make lcov understand that?
EDIT: adding minimal repro scenario below
lcov_repro_one_bad.cpp:
#include <stdexcept>
class Parent {
public:
Parent() throw() { }
virtual void * Do_stuff(const unsigned m) throw(std::runtime_error) =0;
};
class Child : public Parent {
public:
Child() throw();
virtual void * Do_stuff(const unsigned m)
throw(std::runtime_error);
};
Child::Child()
throw()
: Parent()
{
}
void * Child::Do_stuff(const unsigned m)
throw(std::runtime_error)
{
const int a = m;
if ( a > 10 ) {
throw std::runtime_error("oops!");
}
return NULL;
}
int main()
{
Child c;
c.Do_stuff(5);
try {
c.Do_stuff(11);
}
catch ( const std::runtime_error & ) { }
return 0;
}
makefile:
GPP_FLAGS:=-fprofile-arcs -ftest-coverage -pedantic -pedantic-errors -W -Wall -Wextra -Werror -g -O0
all:
g++ ${GPP_FLAGS} lcov_repro_one_bad.cpp -o lcov_repro_one_bad
./lcov_repro_one_bad
lcov --capture --directory ${PWD} --output-file lcov_coverage_all.info --base-directory ${PWD}
lcov --output-file lcov_coverage_filtered.info --extract lcov_coverage_all.info ${PWD}/*.*
genhtml --output-directory lcov_coverage_html lcov_coverage_filtered.info --demangle-cpp --sort --legend --highlight
And here's the coverage I get from that: http://gints.dyndns.info/lcov_repro_bin/lcov_coverage_html/gints/lcov_repro/lcov_repro_one_bad.cpp.gcov.html
As you can see, the supposedly not-hit lines are the definitions of what exceptions the functions may throw, and the extra not-hit constructor for Child is still there in the functions list (click on functions at the top).
I've tried removing the throw declarations from the function definitions, and that takes care of the un-executed lines at the function declarations: http://gints.dyndns.info/lcov_repro_bin/lcov_coverage_html/gints/lcov_repro/lcov_repro_one_v1.cpp.gcov.html (the extra constructor is still there, as you can see).
I've tried moving the function definitions into the class body, instead of defining them later, and that gets rid of the extra constructor: http://gints.dyndns.info/lcov_repro_bin/lcov_coverage_html/gints/lcov_repro/lcov_repro_one_v2.cpp.gcov.html (there's still some weirdness around the Do_stuff function definition, though, as you can see).
And then, of course, if I do both of the above, all is well: http://gints.dyndns.info/lcov_repro_bin/lcov_coverage_html/gints/lcov_repro/lcov_repro_one_ok.cpp.gcov.html
But I'm still stumped as to what the root cause of this is ... and I still want to have my methods (including the constructor) defined in a separate .cpp file, not in the class body, and I do want my functions to have well defined exceptions they can throw!
Here's the source, in case you feel like playing around with this: http://gints.dyndns.info/lcov_repro_src.zip
Any ideas?
Thanks!
OK, after some hunting around & reading up on C++ exception declarations, I think I understand what's going on:
As far as the un-hit throw declarations are concerned, it seems everything is actually correct here: function throw declarations are supposed to add extra code to the output object file that checks for illegal (as far as the throw declaration is concerned) exceptions thrown. Since I was not testing the case of this happening, it makes sense that that code was never executed, and those statements were marked un-hit. Although the situation is far from ideal here anyway, at least one can see where this is coming from.
As far as the duplicate constructors are concerned, this seems to be a known thing with gcc with a longstanding discussion (and various attempts at patches to resolve the resulting object code duplication): http://gcc.gnu.org/bugzilla/show_bug.cgi?id=3187 - basically, there are two versions of the constructor created - one for use with this class, and one for use with child classes, and you need to exercise both, if you want 100% coverage.

Why is passing a char* to this method failing?

I have a C++ method such as:
bool MyClass::Foo(char* charPointer)
{
return CallExternalAPIFunction(charPointer);
}
Now I have some static method somewhere else such as:
bool MyOtherClass::DoFoo(char* charPointer)
{
return _myClassObject.Foo(charPointer);
}
My issue is that my code breaks at that point. It doesn't exit the application or anything, it just never returns any value. To try and pinpoint the issue, I stepped through the code using the Visual Studio 2010 debugger and noticed something weird.
When I step into the DoFoo function and hover over charPointer, I actually see the value it was called with (an IP address string in this case). However, when I step into Foo and hover over charPointer, nothing shows up and the external API function call never returns (it's like it's just stepped over) and my program resumes it's execution after the call to DoFoo.
I also tried using the Exception... feature of the VS debugger (to pick up first chance exceptions) but it never picked up anything.
Has this ever happened to anyone? Am I doing something wrong?
Thank you.
You need to build the project with Debug settings. Release settings mean that optimizations are enabled and optimizations make debugging a beating.
Without optimizations, there is a very close correspondence between statements in your C++ code and blocks of machine code in the program. The program is slower (often far slower) but it's easier to debug because you can observe what each statement does.
The optimizer reorders your code, eliminates variables, inlines functions, unrolls loops, and does all sorts of other things to make the program fast. The program is faster (often much faster) but it's far more difficult to debug because the correspondence between the statements in your C++ code and the instructions in the machine code is no longer there.

How to make Visual C++ 9 not emit code that is actually never called?

My native C++ COM component uses ATL. In DllRegisterServer() I call CComModule::RegisterServer():
STDAPI DllRegisterServer()
{
return _Module.RegisterServer(FALSE); // <<< notice FALSE here
}
FALSE is passed to indicate to not register the type library.
ATL is available as sources, so I in fact compile the implementation of CComModule::RegisterServer(). Somewhere down the call stack there's an if statement:
if( doRegisterTypeLibrary ) { //<< FALSE goes here
// do some stuff, then call RegisterTypeLib()
}
The compiler sees all of the above code and so it can see that in fact the if condition is always false, yet when I inspect the linker progress messages I see that the reference to RegisterTypeLib() is still there, so the if statement is not eliminated.
Can I make Visual C++ 9 perform better static analysis and actually see that some code is never called and not emit that code?
Do you have whole program optimization active [/GL]? This seems like the sort of optimization the compiler generally can't do on its own.
Are you sure the code isn't eliminated later in the compilation/linking process? Have you checked the generated ASM?
How is the RegisterTypeLib function defined? Of course anything marked dllexportcan't be eliminated by the linker, but also any function not marked static (or placed in an anonymous namespace) can be referenced by multiple translation units, so the compiler won't be able to eliminate the function.
The linker can do it, but that might be one of the last optimizations it performs (I have no clue of the order in which it applies optimizations), so the symbols might still be there in the messages you're looking at, even if they're eliminated afterwards.
any code that is successfully inlined will only be generated if called. That's a simple way to do it, as long as the compiler will take the hint. inline is only a suggestion though
The inner call to AtlComModuleRegisterServer has external linkage, which generally prevents the optimizer from propagating the bRegTypeLib value down the call graph. Some of this can be better reasoned with in the disassembly.
So DllInstall(...) calls CAtlDllModuleT::RegisterServer(0). This is the start of the problem:
push 0
call ?DllRegisterServer#?$CAtlDllModuleT#VCAtlTestModule###ATL##QAEJH#Z
Let's just say for arguments sake that the compiler has verified CAtlDllModuleT::DllRegisterServer is only called once and it's very safe to push the 0/FALSE down one more level... the external linkage prevents discarding AtlComModuleRegisterServer, inlining it has a high cost (code duplication) and doesn't allow any additional whole-program optimizations. It is probably safer to keep the signature as-is and bail out early with a regular cdecl call...
?DllRegisterServer#?$CAtlDllModuleT#VCAtlTestModule###ATL##QAEJH#Z proc near
<trimmed>
push 0
push edx
push offset ATL::_AtlComModule
call _AtlComModuleRegisterServer#12
This code can be improved in size due to the two constants, but it's likely to cost about the same amount of runtime. If performance is an issue consider explicitly setting the function layout order, you might save a page fault.
Turns out the key is to enable link-time code generator all the way through the compiler settings.
It must be enabled on the General tab - Whole program optimization must be set to "Use link-time code generation". It must also be enabled on the C++ -> Optimization tab - "Whole program optimization* must be set to "Enable link-time code generation". It must also be enabled on the Linker -> Optimization tab - Link Time Code Generation must be set to "Use Link Time Code Generation". Then /OPT:REF and /OPT:ICF (again, *Linker -> Optimization" tab) must both be enabled.
And this effectively removes the calls to RegisterTypeLib() - it is no longer in the list of symbols imported.