GCOV/LCOV ignores `used functions` declared before an `unused function` - c++

The question may seem weird.
I tried to use GCOV/LCOV for my small project and practiced with simple code before applying it. While practicing it, I encountered an error that I had no idea how to solve.
The report created by LCOV showed that the functions declared before the unused function inside the source code file are reported as unused functions. In contrast, the functions displayed correct outputs when the binary file was executed.
The followings are actual codes used for the practice.
# makefile
CC = g++
CFLAG = -g -fPIC -fprofile-arcs -ftest-coverage
RM = rm -rf
main.o : main.cpp
$(CC) $(CFLAG) -c -Wall -Werror main.cpp
dummy_class.o : dummy_class.cpp
$(CC) $(CFLAG) -c -Wall -Werror dummy_class.cpp
build : main.o dummy_class.o
$(CC) $(CFLAG) -o main main.o dummy_class.o
gcov: main.cpp dummy_class.cpp
gcov main.cpp dummy_class.cpp
coverage.info: gcov
lcov --capture --directory . --output-file coverage.info
lcov -remove coverage.info "/usr/include/*" "/usr/local/include/*" --output-file coverage.info
report : coverage.info
genhtml coverage.info --output-directory ./out
clean :
rm -f main
rm -f *.o *.so *.gcno *.gcda *.gcov coverage.info
rm -r out
do :
make build
./main
make report
// dummy_class.hpp
#pragma once
void func_even_case(void);
void func_odd_case(void);
void func_not_reachable(void);
void dummy(void);
void dummy2(void);
void dummy3(void);
// dummy_class.cpp
#include <iostream>
#include <vector>
#include "dummy_class.hpp"
void func_even_case(void)
{
std::cout << "This is even case" << std::endl;
}
void func_odd_case(void)
{
std::cout << "This is odd case" << std::endl;
}
void func_not_reachable(void)
{
std::cout << "This is not reachable" << std::endl;
}
void dummy(void)
{
std::cout << "This is dummy1." << std::endl;
}
void dummy2(void)
{
std::cout << "This is dummy2." << std::endl;
}
void dummy3(void)
{
std::cout << "This is dummy3." << std::endl;
}
// main.cpp
#include <iostream>
#include "dummy_class.hpp"
int main(void)
{
for (int i = 0; i < 10; ++i)
{
if (i % 2 == 0)
{
func_even_case();
}
else if (i % 2 != 0)
{
func_odd_case();
}
else
{
func_not_reachable();
}
}
func_not_reachable();
dummy();
dummy2();
dummy3();
return 0;
}
When func_not_reachable() is placed outside the for-loop, the report returns
Overall coverage rate:
lines......: 96.7% (29 of 30 lines)
functions..: 100.0% (7 of 7 functions)
and the result is expected.
When func_not_reachable() is removed, the expected result was
Overall coverage rate:
lines......: 86.5% (25 of 29 lines)
functions..: 100.0% (6 of 7 functions)
since func_not_reachable() is the one that will not be executed.
However, the actual result was
Overall coverage rate:
lines......: 65.5% (19 of 29 lines)
functions..: 57.1% (4 of 7 functions)
If the dummy_class.cpp is modified as following
#include <iostream>
#include <vector>
#include "dummy_class.hpp"
void func_even_case(void)
{
std::cout << "This is even case" << std::endl;
}
void func_odd_case(void)
{
std::cout << "This is odd case" << std::endl;
}
void dummy(void)
{
std::cout << "This is dummy1." << std::endl;
}
void dummy2(void)
{
std::cout << "This is dummy2." << std::endl;
}
void dummy3(void)
{
std::cout << "This is dummy3." << std::endl;
}
// unused function declared at the end of the source code.
void func_not_reachable(void)
{
std::cout << "This is not reachable" << std::endl;
}
The report result becomes follows.
Overall coverage rate:
lines......: 34.5% (10 of 29 lines)
functions..: 14.3% (1 of 7 functions)
I am sure I made errors while using GCOV and LCOV, but I cannot figure out where I made a mistake.
Can someone tell me where I made a mistake?
The above code was executed on the following.
Ubuntu 20.04.4 LTS
g++ (Ubuntu 11.1.0-1ubuntu1~20.04) 11.1.0
gcov (Ubuntu 9.3.0-17ubuntu1~20.04) 9.3.0
lcov: LCOV version 1.14

Find out the source of the problem.
The problem was related to the compiler (g++ 11.1.0) or gcov (9.3.0) I used.
The code coverage reported the correct result when the compiler changed from g++ to clang.
To ensure the problem is related to the specific version of the compiler (g++ 11.1.0), I upgraded the system from Ubuntu 20.04.4 LTS to Ubuntu 22.04.4 LTS.
The test condition became as follow
Ubuntu 22.04.4 LTS
g++ (Ubuntu 11.2.0-19ubuntu1) 11.2.0
gcov (Ubuntu 11.2.0-19ubuntu1) 11.2.0
After the update had been made, the code coverage reported the correct result with g++.

Related

C++ - Compile and link multiple files

I have a project with the following structure:
Item.cpp
Item.h
main.cpp
Makefile
The following source code is in the Item.h file:
class Item {
public:
Item();
~Item();
};
The following source code is in the Item.cpp file:
#include <iostream>
#include "Item.h"
Item::Item() {
std::cout << "Item created..." << std::endl;
}
Item::~Item() {
std::cout << "Item destroyed..." << std::endl;
}
The following source code is the content of the main.cpp file:
#include "Item.h"
#include <iostream>
int main() {
std::cout << "Initialize program..." << std::endl;
Item item_1();
std::cout << "Hello world!" << std::endl;
return 0;
}
And finally, the following source code is the Makefile file:
CXX = g++
all: main item
$(CXX) -o sales.o main.o Item.o
main:
$(CXX) -c main.cpp
item:
$(CXX) -c Item.cpp
clean:
rm -rf *.o
When I run the make command and then I run the compiled code with the command ./sales.o, I get the following output:
Initialize program...
Hello world!
Why is the output of the constructor method of the class Item not printed in the console? I found in some web pages that you can compile the source codes in steps and then you can link it with the -o option when using g++ but it does not work in this case. How can I compile this source codes step by step and then link it in the Makefile?
I'm surely you ignored this warning :
warning: empty parentheses were disambiguated as a function declaration [-Wvexing-parse]
#include "Item.h"
#include <iostream>
int main() {
std::cout << "Initialize program..." << std::endl;
Item item_1;
std::cout << "Hello world!" << std::endl;
return 0;
}
just remove parentheses it will be work
test : https://godbolt.org/z/KrdrhvsrW

Can't run terminal(Visual Studio) to read c++ inputs

Thats what I see:
igorz#DESKTOP-QKLDJRN MINGW64 /c/Websites/cpp-series
$ cd "c:\Websites\cpp-series" && g++ gigel.cpp -o gigel && "c:\Websites\cpp-series"gigel
bash: cd: c:\Websites\cpp-series" && g++ gigel.cpp -o gigel && c:Websitescpp-series"gigel: No such file or directory
Thats the code(but the problem is'nt in code I think)
#include <iostream>
int main() {
std::cout << "Hello World!";
return 0;
}

How to resolve Ninja c++ build and execution

I have a C++ project based on CMake that uses Ninja. It's been build and ran using eclipse for C/C++. My current machine is a Mac OS.
The file:
#include <iostream>
#include <exception>
#include <string>
#include <stdexcept>
#include <vector>
#include <cmath>
using namespace std;
class Server {
private:
static int load;
public:
static int compute(long long A, long long B) {
load += 1;
if(A < 0) {
throw std::invalid_argument("A is negative");
}
vector<int> v(A, 0);
int real = -1, cmplx = sqrt(-1);
if(B == 0) throw 0;
real = (A/B)*real;
int ans = v.at(B);
return real + A - B*ans;
}
static int getLoad() {
return load;
}
};
int Server::load = 0;
int main() {
int T;
cin >> T;
while(T--) {
long long A, B;
cin >> A >> B;
/* Enter your code here. */
try{
cout << Server::compute(A, B) << endl;
} catch(invalid_argument e){
cout << "Exception: A is negative" << endl;
} catch(bad_alloc &e){
cout << "Not enough memory" << endl;
} catch(exception &e){
cout << "Exception: ";
cout << e.what() << endl;
} catch(...){
cout << "Other Exception" << endl;
}
}
cout << Server::getLoad() << endl;
return 0;
}
Build info:
cmake --build . -- -v
[1/2] /Library/Developer/CommandLineTools/usr/bin/c++ -O3 -DNDEBUG -isysroot /Library/Developer/CommandLineTools/SDKs/MacOSX10.14.sdk -MD -MT CMakeFiles/deleteme.dir/deleteme.cpp.o -MF CMakeFiles/deleteme.dir/deleteme.cpp.o.d -o CMakeFiles/deleteme.dir/deleteme.cpp.o -c ../../deleteme.cpp
[2/2] : && /Library/Developer/CommandLineTools/usr/bin/c++ -O3 -DNDEBUG -isysroot /Library/Developer/CommandLineTools/SDKs/MacOSX10.14.sdk -Wl,-search_paths_first -Wl,-headerpad_max_install_names CMakeFiles/deleteme.dir/deleteme.cpp.o -o deleteme && :
Build complete (0 errors, 0 warnings):
When I run:
Building in:
cmake --build . -- -v
ninja: no work to do.
Build complete (0 errors, 0 warnings):
It does not give me the chance to input the values. It just skips everything and finishes execution. If I put a cout right at the beginning, then the program works as expected.
Why is this happening?
Ps: The project complete path was removed from here for safety reasons. And yes, my project was created with the name 'deleteme'.
Pss: I took this snippet from HackerRank for studing purposes, so It should be fine. I've only added the try/catch and method call.
You are confusing building your program with running your program.
When you run the command cmake --build . -- -v, cmake will build your project. That means it will launch the appropriate tools to compile and link your program, which will produce an executable called deleteme somewhere in your build directory.
The subsequent invocation of the same command correctly reports that no work needs to be done (since you presumably haven't modified any of the source code between invocations).
To be clear, normally this will not run your program, which is why you don't get a prompt to input any values.
To run your program, which, if I understand correctly is what you are trying to do, simply run the executable deleteme that was produced by the build process. You will most likely find this executable in the build directory, that is, the directory where you ran the cmake --build . command. (Depending on your CMake project structure, you may also find it in a subdirectory of your build directory.)
I've figured It out how to solve this. I don't know what have caused It. It looks like ninja is not need if you have properly configured your environment variables, related to your compiler, inside Eclipse.
After doing that, everything works fine.

undefined reference to `__gcov_flush'

I am trying same,
http://www.linuxforums.org/forum/suse-linux/135465-gcov-g.html
Code from the link,
#include <iostream>
using namespace std;
void one(void);
void two(void);
void __gcov_flush(void);
int main(void)
{
int i;
while(true)
{
__gcov_flush();
cout << "Enter a number(1-2), 0 to exit " << endl;
cin >> i;
if ( i == 1 )
one();
else if ( i == 2 )
two();
else if ( i == 0 )
break;
else
continue;
}
return 0;
}
void one(void)
{ cout << "One is called" << endl; }
void two(void)
{ cout << "Two is called" << endl; }
but for me also it gives,
test.cpp:(.text+0x1d9): undefined reference to `__gcov_flush()'
collect2: ld returned 1 exit status
Tried the followings,
g++ -fprofile-arcs test.cpp
g++ -fprofile-arcs -g test.cpp
g++ -fprofile-arcs -ftest-coverage -g test.cpp
g++ -fprofile-arcs -ftest-coverage -g test.cpp -lgcov
I have also tried the "-lgcov" & "extern void __gcov_flush(void)" as mentioned in link above. I am currently on Ubuntu12.04 and g++ 4.6
So, I want to know if there is solution for this or gcov_flush doesnt work anymore.
void __gcov_flush();
Since the code is compiled as C++, this declares the existence of a C++ function of that name. C++ functions are subject to name mangling, so the (C++) symbol is not found in the (C) link library, and the linker (rightfully) complains about it.
If you declare the function, declare it as a function with C linkage:
extern "C" void __gcov_flush();
This should do the trick.
Note the commend by Paweł Bylica -- __gcov_flush() has been removed in GCC 11, you should use __gcov_dump().
I fixed this issue changing the settings.
Test Project --> Build Settings
Instrument Program Flow = Yes

Why is the mongo C++ driver giving me compilation errors?

I have installed mongo straight from github using
sudo scons --full install
and have the following example source file
#include <cstdlib>
#include <iostream>
#include <mongo/client/dbclient.h>
void run() {
mongo::DBClientConnection c;
c.connect("localhost");
}
int main() {
try {
run();
std::cout << "connected ok" << std::endl;
} catch( const mongo::DBException &e ) {
std::cout << "caught " << e.what() << std::endl;
}
return EXIT_SUCCESS;
}
When I run
g++ tutorial.cpp -pthread -lmongoclient -lboost_thread-mt -lboost_filesystem
-lboost_program_options -lboost_system -o tutorial
I am given the error
In file included from /usr/local/include/mongo/util/net/hostandport.h:21:0,
from /usr/local/include/mongo/util/net/message.h:24,
from /usr/local/include/mongo/client/dbclientinterface.h:30,
from /usr/local/include/mongo/client/connpool.h:23,
from /usr/local/include/mongo/client/dbclient.h:32,
from tutorial.cpp:3:
/usr/local/include/mongo/db/server_options.h:34:51: fatal error:
mongo/util/options_parser/environment.h: No such file or directory
compilation terminated.
I looked into /usr/local/include/mongo/util, but the options_parser folder is not in there.
I had the same error myself, after following the write-up on MongoDB's website. What I ended up doing was copying the headers from the download directory to my include directory. I.e.
sudo cp -R ~/Downloads/mongo-master/src/mongo/util/options_parser /usr/local/include/mongo/util/
Where mongo-master is the name of the extracted directory from MongoDB's GitHub. Hopefully this helps you.