I have two main functions that use a common C++ class.
File1: main.cpp
#include <iostream>
#include "HelloAnother.h"
int main() {
HelloAnother::sayHello1();
return 0;
}
File2: main2.cpp
#include <iostream>
#include "HelloAnother.h"
int main() {
HelloAnother::sayHello2();
return 0;
}
File3: HelloAnother.h
#pragma once
class HelloAnother {
public:
static void sayHello1();
static void sayHello2();
};
File4: HelloAnother.cpp
#include <iostream>
#include "HelloAnother.h"
void HelloAnother::sayHello1() {
std::cout << "Hello 1!!!" << std::endl;
}
void HelloAnother::sayHello2() {
std::cout << "Hello 2 !!!" << std::endl;
}
Now I compile two executables:
clang-3.8 -o main -fprofile-arcs -ftest-coverage --coverage -g -fPIC -lstdc++ main.cpp HelloAnother.cpp
clang-3.8 -o main2 -fprofile-arcs -ftest-coverage --coverage -g -fPIC -lstdc++ main2.cpp HelloAnother.cpp
Now, I run ./main
Hello 1!!!
When I rerun ./main
Hello 1!!!
profiling: /media/sf_ubuntu-shared/test-profiling/main.gcda: cannot map: Invalid argument
profiling: /media/sf_ubuntu-shared/test-profiling/HelloAnother.gcda: cannot map: Invalid argument
One second run, I get this error (above) in trying to create/merge .gcda files.
Now, If I try to run ./main2
Hello 2 !!!
profiling: /media/sf_ubuntu-shared/test-profiling/HelloAnother.gcda: cannot map: Invalid argument
When I generate the code coverage report, the call to second function doesn't show up as if the call wasn't made.
Can anyone help me debug this issue pls? The issue seems to be related to merging of .gcda files on multiple runs, but not sure how to solve it.
I also tried clang-3.5 but with same results.
After a lot of searching and trial/error this is what works for me:
Compile first executable, run it. This generates HelloAnother.gcda and main.gcda files.
Execute lcov --gcov-tool=gcov-4.4 --directory . --capture --output-file coverage.main.info
rm -rf *.gcda; rm -rf *.gcno
Compile second executable (main2.cpp), run it. This generates another HelloAnother.gcda and a main2.gcda file.
Execute lcov --gcov-tool=gcov-4.4 --directory . --capture --output-file coverage.main2.info
Now to generate nice looking html report do: genhtml -o coverage coverage.main.info coverage.main2.info
Your problem is that you compile the shared file (HelloAnother.cc) twice and gcov fails to understand that two copies of HelloAnother.o inside main1 and main2 need to be shared.
Instead, compile the shared code once and link it into each executable:
$ g++ --coverage -c HelloAnother.cc
$ g++ --coverage main1.cc HelloAnother.o -o main1
$ g++ --coverage main2.cc HelloAnother.o -o main2
$ ./main1
Hello 1!!!
$ ./main2
Hello 2 !!!
$ gcov --stdout HelloAnother.gcno
...
1: 4:void HelloAnother::sayHello1() {
1: 5: std::cout << "Hello 1!!!" << std::endl;
1: 6:}
-: 7:
1: 8:void HelloAnother::sayHello2() {
1: 9: std::cout << "Hello 2 !!!" << std::endl;
1: 10:}
-: 11:
Related
I have a simple C++ program which I compile with clang using the Boost library and with C++14 support.
I use the following command to compile my sample.cpp file and it works fine:
clang++ -g -std=c++1y -I$BOOST_ROOT sample.cpp -o sample
where $BOOST_ROOT is the path to where I downloaded and extracted the boost zip file.
$BOOST_ROOT=/usr/local/boost_1_66_0/
When I try to compile the same sample.cpp file with a makefile, it doesn't work.
This is what my makefile looks like:
sample: sample.cpp
clang++ -g -std=c++1y -I$BOOST_ROOT sample.cpp -o sample
Running make command, I get the error:
Sample.cpp:9:10: fatal error: 'boost/format.hpp' file not found
#include <boost/format.hpp>
^~~~~~~~~~~~~~~~~~
1 error generated.
And here is the sample.cpp
//
// sample.cpp
//
//
#include <iostream>
#include <boost/format.hpp>
using namespace std;
int main()
{
std::cout << "Enter your first name: " << std::endl;
std::string firstName;
std::cin >> firstName;
std::cout << "Enter your surname: " << std::endl;
std::string surname;
std::cin >> surname;
auto formattedName = str( boost::format("%1% %2%"s) % firstName % surname );
std::cout << "You said your name is: " << formattedName << std::endl;
return 0;
}
CONSOLE OUTPUT
MacBook-Air:Listing_1_7 userd43f$ make
c++ sample.cpp -o sample
sample.cpp:9:10: fatal error: 'boost/format.hpp' file not found
#include <boost/format.hpp>
^~~~~~~~~~~~~~~~~~
1 error generated.
make: *** [sample] Error 1
MacBook-Air:Listing_1_7 userd43f$ ls $BOOST_ROOT
INSTALL boost boost.png bootstrap.sh index.html rst.css
Jamroot boost-build.jam boostcpp.jam doc libs status
LICENSE_1_0.txt boost.css bootstrap.bat index.htm more tools
The problem was that there were spaces instead of a tab in the command-line of my makefile.
BOOST_ROOT := /usr/local/boost_1_66_0
BOOST_INC := ${BOOST_ROOT}/include
sample: sample.cpp
clang++ -g -std=c++1y -I$(BOOST_ROOT) sample.cpp -o sample
In the last line just before clang++ command I was using spaces instead of a TAB. I replaced all the spaces with a single TAB before clang++, and also I needed to put the BOOST_ROOT inside the parentheses as (mentioned by #MaximEgorushkin)
Then it started picking up the right command, as shown in the output below:
MacBook-Air:Listing_1_7 userd43f$ make
clang++ -g -std=c++1y -I/usr/local/boost_1_66_0 sample.cpp -o sample
Boost root directory normally has include and lib directories in it.
It should probably be:
BOOST_ROOT := /usr/local/boost_1_66_0
BOOST_INC := ${BOOST_ROOT}/include
sample: sample.cpp
clang++ -g -std=c++1y -I${BOOST_INC} sample.cpp -o sample
I am attempting to generate code coverage for a small test library. The library only consists of two files.
calculator.cpp:
#include "calculator.h"
Calculator::Calculator()
{
}
Calculator::~Calculator()
{
}
void Calculator::addNumbers(int x, int y)
{
this->result = x + y;
}
calculator.h:
#ifndef CALCULATOR_H
#define CALCULATOR_H
class Calculator
{
public:
Calculator();
~Calculator();
void addNumbers(int x, int y);
};
#endif
I have a unit test for this library that is being executed. It includes the library and runs fine. I have set the cmake_cxx_flags to include -fprofile-arcs and -ftest-coverage in the top level CMakeLists.txt.
cmake_minimum_required(VERSION 2.8.11)
set(CMAKE_CXX_FLAGS "-std=c++11")
include_directories("${PROJECT_BINARY_DIR}")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -g -O0 --coverage")
#set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -g -O0 --coverage -ftest-coverage -fprofile-arcs")
add_subdirectory(src)
add_subdirectory(test)
I am using a script to take the gcno and gcda files that are generated on build to generate a human readable report.
#!/bin/bash
OUTPUT_DIR="$1/bin/ExecutableTests/Coverage"
mkdir -p "$OUTPUT_DIR"
component=Calculator
dependency=calculator
script=test_calculator.sh
unit_test=unit_test_calculator
mkdir $OUTPUT_DIR/$component
cd "$1"/bin/
make clean || exit 1
make || exit 1
# Create baseline coverage
lcov -c -i -d "$1"/bin/src/"$component"/CMakeFiles/"$dependency".dir -o "$1/Coverage/$component"_"$dependency".coverage.base
# Run the test
$1/scripts/$script $1
# Create test coverage
lcov -c -d "$1"/bin/test/$component/CMakeFiles/"$unit_test".dir -o "$1/Coverage/$component"_"$dependency".coverage.run
lcov -d "$1/test/$component" -a "$1/Coverage/$component"_"$dependency".coverage.base -a "$1/Coverage/$component"_"$dependency".coverage.run -o "$1/Coverage/$component"_"$dependency".coverage.total
genhtml --branch-coverage -o "$OUTPUT_DIR/$component" "$1/Coverage/$component"_"$dependency".coverage.total
rm -f "$1/Coverage/$component"_"$dependency".coverage.base "$1/Coverage/$component"_"$dependency".coverage.run "$1/Coverage/$component"_"$dependency".coverage.total
I can see that the data files are being generated for the library; however when I view the report that is generated from the script it shows that the library is never touched. This is clearly wrong as illustrated by my unit test.
#include "lest_basic.hpp"
#include "calculator.h"
#include <memory>
#include <iostream>
int addResult(int x, int y)
{
Calculator calc1;
return calc1.addNumbers(x, y);
}
const lest::test specification[] =
{
CASE( "Addition" )
{
std::cout << "Starting Addition testing..." << std::endl;
std::cout << "Adding 1 and 2..." << std::endl;
EXPECT(addResult(1, 2) == 3);
std::cout << "Adding 2 and 8..." << std::endl;
EXPECT(addResult(2, 8) > 1);
std::cout << "Adding 7 and 4..." << std::endl;
EXPECT(addResult(7, 4) < 12);
},
};
int main(int argc, char **argv) {
return lest::run( specification );
}
Here is the CMakeLists.txt for my unit test:
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_SOURCE_DIR}/bin/ExecutableTests/)
include_directories(${CMAKE_SOURCE_DIR}/externalinclude/)
include_directories(${CMAKE_SOURCE_DIR}/src/Calculator/)
add_executable (unit_test_calculator test_calculator.cpp)
target_link_libraries(unit_test_calculator -Wl,--whole-archive calculator -Wl,--no-whole-archive)
My question is why is the report saying that the library code isn't be covered? Are the data files the problem?
I have fixed my issue. The problem was that I wasn't running lcov against the source code after running the unit test. I had the wrong directory.
lcov -c -d "$1"/bin/test/$component/CMakeFiles/"$unit_test".dir -o "$1/Coverage/$component"_"$dependency".coverage.run
Needed to be:
lcov -c -d "$1"/bin/src/$component/CMakeFiles/"$dependency".dir -o "$1/Coverage/$component"_"$dependency".coverage.run
Set up MinGW and Netbeans. Only working withe othere IDE's and compilers in before. My machine is x64 win7x64. I'm not shure if I only installed the 32bit version of MinGW.
Compiling a simpel Helle World in x64 leeds to:
g++ -m64 -c -g -MMD -MP -MF "build/Debug/MinGW-Windows/main.o.d"
-o build/Debug/MinGW-Windows/main.o main.cpp
//Message: sorry, unimplemented: 64-bit mode not compiled in
The win32 Version compiles fine.
// ---
g++ -m32 -c -g -MMD -MP -MF "build/Debug/MinGW-Windows/main.o.d"
-o build/Debug/MinGW-Windows/main.o main.cpp
// Compiles without any error...
Starting the 32-Version it prints only one message and terminats withe a segmentation fault before returning from first std:cout. Using ftream, to make a file output same error occures.
The demo-Programm of netbeans "Welcome" throws the same exceptions.
#include <cstdlib>
#include <iostream> // EDIT! (worked at this post long time sry.)
using namespace std;
int main(int argc, char** argv) {
int i = 0; // for making shure, program is working before calling fs.open
std::cout << "hello world blubb" << endl; // this one shows up its message at consol.
//programm aborded.
std::cout << "Now again" << endl; // this on is never reached.
return 0;
}
Errormessages:
Signal received: SIGSEGV ( Segmentation fault )
For programm cppapplication_1 pid 7972
You may discard...
Errormessage windows:
cppapplication_1.exe does not work.
Where can I start my serach? Compiler? some dlls? Dependency Walker?
Thx for any comment =).
Cutton
This is my makefile:
CFLAGS=-Wall -g -O2
clean:
rm -f ex1
And when I run a script, for example, this one (ex3.c):
#include <stdio.h>
int main()
{
int age = 10;
int height = 72;
printf("I am %d years old.\n", age);
printf("I am %d inches tall.\n", height);
return 0;
}
I get the following error:
$ g++ Makefile.c -o makefile
Makefile.c:1:1: error: 'CFLAGS' does not name a type
CFLAGS=-Wall -g
^g++ ex3.c -o ex3
$
Please don't compile the makefile.
Use the make utility instead.
Synonyms include nmake and gmake.
The makefile should be passed to the make program or build utility.
Please help me, How to access run time varibale's data(att) in stub.exe of att variable that is defined in proc.so,
I have created proc.so and linked with attol.exe and stub.exe and
attol.exe updates 'att' variable and stub.exe is accessing 'att' variable and prints att's value.
I have used below commands to compile the code :
g++ -Wall -c attol.cc proc.cc stub.cc
g++ -shared -dynamiclib -fPIC -o libproc.so proc.o -ldl
g++ -rdynamic -o attol.exe attol.o /users/hbharti/DLOPEN/proc/libproc.so -ldl
g++ -rdynamic -o stub.exe stub.o /users/hbharti/DLOPEN/proc/libproc.so -ldl
When i am running both .exe at different terminal then attol.exe showing 'att:4' value but stub.exe is showing incorrect value,
But stub.exe should display '4' value or updated value.
out put attol.exe:
./attol.exe
Value of att is : 4
Enter the value of att :
out put stub.exe:
./stub.exe
Att : 0
----Complete Code Details----
proc.h:
#ifndef __X_H_INCLUDED__
#define __X_H_INCLUDED__
extern int att;
int fun();
#endif
proc.cc:
#include<iostream.h>
#include "proc.h"
int att;
int fun ()
{
att=4;
return 0;
}
Above code is generating proc.o and then this proc.o will converted into proc.so with below commands:
g++ -Wall -c attol.cc proc.cc stub.cc
g++ -shared -dynamiclib -fPIC -o libproc.so proc.o -ldl
attol.cc:
#include <iostream.h>
#include "proc.h"
using namespace std;
int main ()
{
int ch=1;
fun();
cout<<"\n Value of att is : "<<att;
do{
cout<<"\n Enter the value of att : ";
cin>>att;
cout<<"\n Do you want to continue the : ";
cin>>ch;
}while(ch!=0);
return 0;
}
attol.cc file creates attol.exe by using below command
g++ -rdynamic -o attol.exe attol.o /users/hbharti/DLOPEN/proc/libproc.so -ldl
out put:
Value of att is : 4
Enter the value of att :
stub.cc:
#include <iostream.h>
#include <dlfcn.h>
int main ()
{
void *handle;
char *error;
handle = dlopen ("/users/hbharti/DLOPEN/proc/libproc.so", RTLD_LAZY);
if (!handle) {
fputs (dlerror(), stderr);
exit(1);
}
int *att =(int*) dlsym(handle, "att");
if ((error = dlerror()) != NULL) {
fputs(error, stderr);
exit(1);
}
cout<<"\n Att : " <<*att;
cout<<"\n " ;
dlclose(handle);
}
stub.cc file creates stub.exe by using below command
g++ -rdynamic -o stub.exe stub.o /users/hbharti/DLOPEN/proc/libproc.so -ldl
Judging by the code, there seems to be a fundamental issue with the core-logic.
A shared-object (*.so) is loaded into the executing process's memory address space.
However it is NOT shared across multiple processes. When 2 or more executables attempt to access the same shared-object (*.so), they both get independent copies of it mapped into their respective memory address spaces.
Data (even globals) within a shared-object (*so) are NOT shared across 2 or more executables.