I use boost test for unit testing and gcov and lcov for measuring the coverage.
Unfortuanlly genhtml generates reports like that for function coverage:
I now want to know what the function _ZN7UtilLib11ProgressBarC2EjdRSo actually is.
So far I can not correlate this function to any of the class interface of ProgressBar:
class ProgressBar {
public:
explicit ProgressBar(
unsigned int expected_count,
double updateInterval = 30,
std::ostream& os = std::cout);
unsigned int operator+=(unsigned int increment);
unsigned int operator++();
unsigned int operator++(int i);
}
Can any one help me how to either get better function names with gcov or how does one understand these function names.
The application is compiled with gcc4.7 with the following flags:-g -g -save-temps=obj -Wall -Wextra -Wno-unused-parameter -Wno-error=unused-parameter -O0 -pedantic
These are mangled C++ symbols, use c++filt in a shell to demangle it:
> c++filt _ZN7UtilLib11ProgressBarC2EjdRSo
UtilLib::ProgressBar::ProgressBar(unsigned int, double, std::basic_ostream<char, std::char_traits<char> >&)
Also, since you seem to use genhtml, check out the --demangle-cpp option to do the demangling automatically for you.
Note that the compiler emits two implementations for the ctor you wrote, using --demangle-cpp will hide the difference which is visible only in the mangled symbol name. To understand what the compiler is doing, have a look here.
Use c++filt, like this:
$c++filt -n _ZN7UtilLib11ProgressBarC2EjdRSo
which outputs:
UtilLib::ProgressBar::ProgressBar(unsigned int, double, std::basic_ostream<char, std::char_traits<char> >&)
Related
I am struggling with a port of an open-source tool to Solaris. Most things work, cmake/pkg-config/etc. are there, dependencies are found, gmake works, compiler and linker calls look all fine and tren, boom:
Undefined first referenced
symbol in file
std::qsort(void*, unsigned int, unsigned int, int (*)(const void*, const void*)) ...
This part I don't understand. At the first glance, std::qsort does not make sense, it is supposed to be part of C library, not STL. So I looked into stdlib.h and found a list of things like using std::sort; and dozens of other standard functions like free, malloc, atoi, etc., redirected in case of C++ context.
What is Oracle doing there and why? Which library am I supposed to link with if they do redirect it like this? Or why does CC command not pull that in automatically like GCC does?
I tried adding -lstdc++ but no luck.
Alternatively, the plain libc versions seem to be defined in <iso/stdlib_c99.h> (or <iso/stdlib_iso.h>). Is it legal to include one of those headers directly or will this wreak other random havoc at link time?
Edit:
since there are multiple suspicions of the build system weirdness, here is the basically the linking call from the gmake execution:
/opt/developerstudio12.6/bin/CC -std=c++11 -xO3 -DNDEBUG <i.e. bunch of object files> -o ../systest -L/opt/csw/lib/64 -lintl
I cannot see anything special there and I expect CC to figure out what to link to get the obligatory functionality.
The rule is that #include <xxx.h> puts names into the global namespace and is allowed to also put them in std. Conversely, #include <cxxx> puts names into std and is allowed to also put them into the global namespace. In practice, this means that there are two approaches to implementing the functions from the standard C library in C++: declare the standard C library names in the <xxx.h> headers and hoist those declarations into std in the cxxx headers, or declare the names in std in the headers and hoist those declarations into the global namespace in the <xxx.h> headers. With the former approach, the name of the function will be qsort; with the latter, it will be std::qsort. Either way, that error message usually indicates a setup problem with the compiler. The linker isn’t finding the standard library.
This compile command
/opt/developerstudio12.6/bin/CC -std=c++11 -xO3 -DNDEBUG ...
will produce a 32-bit executable. Per the Oracle CC man page:
On Oracle Solaris, -m32 is the default. On Linux systems supporting 64-bit programs, -m64 -xarch=sse2 is the default.
But this library option
-L/opt/csw/lib/64
is searching a directory full of 64-bit libraries.
Either add -m64 to the compile command or use the 32-bit library path.
Update
The question almost certainly would be answerable had it included the full error message, which is almost certainly something like this:
CC -g qsort.cc -o qsort
"qsort.cc", line 15: Error: Could not find a match for std::qsort(int[4], unsigned, unsigned, int(void*,void*)) needed in main(int, char**).
"/usr/include/iso/stdlib_iso.h", line 184: Note: Candidate 'std::qsort(void*, unsigned, unsigned, extern "C" int(*)(const void*,const void*))' is not viable: argument '4' can't be converted from 'int(void*,void*)' to 'extern "C" int(*)(const void*,const void*)'.
"/usr/include/iso/stdlib_iso.h", line 187: Note: Candidate 'std::qsort(void*, unsigned, unsigned, int(*)(const void*,const void*))' is not viable: argument '4' can't be converted from 'int(void*,void*)' to 'int(*)(const void*,const void*)'.
This code works just fine when compiled with Oracle Developer Studio 12.6 on Solaris 11.4:
#include <stdlib.h>
int compare( const void *p1, const void *p2 )
{
int i1 = *( ( int * ) p1 );
int i2 = *( ( int * ) p2 );
return( i1 - i2 );
}
int main( int argc, char **argv )
{
int array[ 4 ] = { 5, 8, 12, 4 };
qsort( array, sizeof( array ) / sizeof( array[ 0 ] ),
sizeof( array[ 0 ] ), &compare );
}
#include <stdio.h>
// xyz will be emitted with -flto (or if it is static) even when
// the function is unused
__attribute__((__used__))
void xyz() {
printf("Hello World!\n");
}
int main() {
return 0;
}
What do I need this for?
Is there any way I could still reach xyz somehow besides directly calling the function, like some dlsym() like magic?
Attribute used is helpful in situation when you want to force compiler to emit symbol, when normally it may be omitted. As GCC's documentation says (emphasis mine):
This attribute, attached to a function, means that code must be
emitted for the function even if it appears that the function is not
referenced. This is useful, for example, when the function is
referenced only in inline assembly.
For instance, if you have code as follows:
#include <iostream>
static int foo(int a, int b)
{
return a + b;
}
int main()
{
int result = 0;
// some inline assembly that calls foo and updates result
std::cout << result << std::endl;
}
you might notice, that no symbol foo is present with -O flag (optimization level -O1):
g++ -O -pedantic -Wall check.cpp -c
check.cpp:3: warning: ‘int foo(int, int)’ defined but not used
nm check.o | c++filt | grep foo
As a result you cannot reference foo within this (imaginary) inline assembly.
By adding:
__attribute__((__used__))
it turns into:
g++ -O -pedantic -Wall check.cpp -c
nm check.o | c++filt | grep foo
00000000 t foo(int, int)
thus now foo can be referenced within it.
You may also have spotted that gcc's warning is now gone, as you have tell you compiler that you are sure that foo is actually used "behind the scene".
A particular usecase is for interrupt service routines in a static library.
For example, a timer overflow interrupt:
void __attribute__((interrupt(TIMERA_VECTOR),used)) timera_isr(void)
This timera_isr is never called by any function in the user code, but it might form an essential part of a library.
To ensure it is linked and there isn't a interrupt vector pointing to an empty section the keyword ensures the linker doesn't optimise it out.
If you declare a global variable or function that is unused, gcc will optimized it out (with warning), but if you declared the global variable or the function with '__attribute__((used))', gcc will include it in object file (and linked executable).
https://gcc.gnu.org/legacy-ml/gcc-help/2013-09/msg00108.html
Another use case is to generate proper coverage information for header files. Functions declared in header files are usually removed by the compiler when unreferenced. Therefore, you will get 100% coverage in your coverage reports even if you forgot to call some functions that are located in the header file. To prevent this, you may mark your function with __attribute__((used)) in your coverage builds.
There is a common C++ bug with uninitialised primitive members:
#include <iostream>
class A {
public:
int x;
};
int main() {
A a;
std::cout << a.x;
return 0;
}
a.x will be uninitialised. I understand why it happens and want to find a solution for catching such bugs. I checked gcc and cppcheck, they don't report these members.
EDIT
Checked gcc with flags -Wall -Wextra -Werror -pedantic -Wold-style-cast -Wconversion -Wsign-conversion -Wunreachable-code
The first version of gcc that detects a bug is 5.1. g++-4.9 doesn't detect it, clang++-3.6 fails too.
Yes they do… sort of:
main.cpp: In function 'int main()':
main.cpp:10:18: warning: 'a.A::x' is used uninitialized in this function [-Wuninitialized]
std::cout << a.x;
^
0
In the above linked example, I'm using GCC 5.1 trunk with -Wall.
Turn on more GCC warnings and/or upgrade.
Also tested, and found not to warn:
GCC 4.4.7
GCC 4.9.2 (by RiaD)
Clang 3.6.0
Honestly I'm not sure what else you can do. You could create a tool to do this, but then you'd be creating a compiler or static analyser. :)
So, I guess, just hope the people who know how to do that catch up…
This bug is diagnosed by valgrind with the (default) tool memcheck, producing a number of warnings, including:
$ valgrind ./unin
…
==12185== Use of uninitialised value of size 8
==12185== at 0x4F39BC3: ??? (in /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.21)
==12185== by 0x4F3AD89: std::ostreambuf_iterator<char, std::char_traits<char> > std::num_put<char, std::ostreambuf_iterator<char, std::char_traits<char> > >::_M_insert_int<long>(std::ostreambuf_iterator<char, std::char_traits<char> >, std::ios_base&, char, long) const (in /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.21)
==12185== by 0x4F3AF8C: std::num_put<char, std::ostreambuf_iterator<char, std::char_traits<char> > >::do_put(std::ostreambuf_iterator<char, std::char_traits<char> >, std::ios_base&, char, long) const (in /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.21)
==12185== by 0x4F474E9: std::ostream& std::ostream::_M_insert<long>(long) (in /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.21)
==12185== by 0x400763: main (in [censored]/unin)
It should also be found by Clang's address sanitizer. However, I realize you are most interested in a compile-time check. After all, the existing test suites may never execute some of the code, and catching a bug sooner is always better. You could use GCC 5.1 (even if you used it only for this purpose), or you could use a dedicated static analyzer. Fortunately, clang comes with a static analyzer invoked as scan-build (included in at least the Debian/Ubuntu packages):
$ scan-build clang -c unin.cxx
scan-build: Using '/usr/lib/llvm-3.6/bin/clang' for static analysis
unin.cxx:10:3: warning: Function call argument is an uninitialized value
std::cout << a.x;
^~~~~~~~~~~~~~~~
1 warning generated.
scan-build: 1 bug found.
I've been reading again Scott Meyers' Effective C++ and more specifically Item 30 about inlining.
So I wrote the following, trying to induce that optimization with gcc 4.6.3
// test.h
class test {
public:
inline int max(int i) { return i > 5 ? 1 : -1; }
int foo(int);
private:
int d;
};
// test.cpp
int test::foo(int i) { return max(i); }
// main.cpp
#include "test.h"
int main(int argc, const char *argv[]) {
test t;
return t.foo(argc);
}
and produced the relevant assembly using alternatively the following:
g++ -S -I. test.cpp main.cpp
g++ -finline-functions -S -I. test.cpp main.cpp
Both commands produced the same assembly as far as the inline method is concerned;
I can see both the max() method body (also having a cmpl statement and the relevant jumps) and its call from foo().
Am I missing something terribly obvious? I can't say that I combed through the gcc man page, but couldn't find anything relevant standing out.
So, I just increased the optimization level to -O3 which has the inline optimizations on by default, according to:
g++ -c -Q -O3 --help=optimizers | grep inline
-finline-functions [enabled]
-finline-functions-called-once [enabled]
-finline-small-functions [enabled]
unfortunately, this optimized (as expected) the above code fragment almost out of existence.
max() is no longer there (at least as an explicitly tagged assembly block) and foo() has been reduced to:
_ZN4test3fooEi:
.LFB7:
.cfi_startproc
rep
ret
.cfi_endproc
which I cannot clearly understand at the moment (and is out of research scope).
Ideally, what I would like to see, would have been the assembly code for max() inside the foo() block.
Is there a way (either through cmd-line options or using a different (non-trivial?) code fragment) to produce such an output?
The compiler is entirely free to inline functiones even if you don't ask it to - both when you use inline keyword or not, or whether you use -finline-functions or not (although probably not if you use -fnoinline-functions - that would be contrary to what you asked for, and although the C++ standard doesn't say so, the flag becomes pretty pointless if it doesn't do something like what it says).
Next, the compiler is also not always certain that your function won't be used "somewhere else", so it will produce an out-of-line copy of most inline functions, unless it's entirely clear that it "can not possibly be called from somewhere else [for example the class is declared such that it can't be reached elsewhere].
And if you don't use the result of a function, and the function doesn't have side-effects (e.g. writing to a global variable, performing I/O or calling a function the compiler "doesn't know what it does"), then the compiler will eliminate that code as "dead" - because you don't really want unnecessary code, do you? Adding a return in front of max(i) in your foo function should help.
I'm compiling and linking a cpp file against a pre-compiled library, and I'm getting an "undefined reference" error.
Firstly, this is the command (the library in question is quicknet3, the program I'm compiling is trapper):
g++ -w -g -I. -g -O3 -pipe -Wall -I/home/install/x86_64/include/quicknet3 -L/home/install/x86_64/lib -lquicknet3 -lintvec -lfltvec -o trapper trapper.cpp CMyException.cpp
Here's the undefined reference error:
/tmp/ccFuVczF.o: In function 'main':
trapper.cpp:1731: undefined reference to 'QN_InFtrLabStream_PFile::QN_InFtrLabStream_PFile(int, char const*, _IO_FILE*, int)'
The call in trapper.cpp (line 1731) is:
IN_PFILE = new QN_InFtrLabStream_PFile(0, "", fp, 1);
where fp is a FILE *, assigned as the result of an fopen call beforehand.
The constructor being called is defined in the relevant header file (QN_Pfile.h), as follows:
class QN_InFtrLabStream_PFile : public
QN_InFtrLabStream
{
public:
QN_InFtrLabStream_PFile(int a_debug, const char* a_dbgname, FILE* a_file, int a_indexed);
(... other declarations ...)
}
The definition of the constructor is indeed given in QN_Pfile.cc:
QN_InFtrLabStream_PFile::QN_InFtrLabStream_PFile(int a_debug,const char* a_dbgname, FILE* a_file, int a_indexed) : log(a_debug, "QN_InFtrLabStream_PFile", a_dbgname),file(a_file),indexed(a_indexed),buffer(NULL),sentind(NULL)
{
(... the usual constructor stuff :P ...)
}
I compiled the quicknet3 library myself, without error, and installed it to /home/install/x86_64/lib/libquicknet3.a
So, I can't understand why the call from trapper.cpp is unable to find the reference to this constructor definition. The g++ arguments of -L/home/install/x86_64/lib -lquicknet3 should do the trick, right?
Any ideas?
Thanks,
Roy
I notice that you're mixing FILE* and _IO_FILE*. I'm not familiar with the latter, are you sure they're one and the same?
A quick workaround is to add /home/install/x86_64/lib/libquicknet3.a to g++ commandline.
I you want to investigate further, if g++ is picking another copy of libquicknet3, you can pass -v to g++ so it will output its searching paths.
FILE is a typedef of _IO_FILE. Your linker is treating it as a unique type.
You could try:
IN_PFILE = new QN_InFtrLabStream_PFile(0, "", (FILE *)fp, 1);
to see if this resolve your constructor.
(FILE is defined in stdio.h, _IO_FILE in libio.h if you're interested)