Anonymous namespace causes undefined reference here - works there - c++

I've written some C++ code for an embedded system which works like a charm. The current task is to emulate the behaviour of this device on a PC. Some of the code has to be ported: For a first test I'm using mingw (g++) while the Embedded system is an STM32 and uses the KEIL µVision toolchain.
I've run into a problem that is not really related to functional behaviour rather than a compiler specific weirdness. I have 2 classes defined in an anonymous namespace because they are included throughout the whole project. Now on the embedded device this compiles and runs without a problem. g++ complains about an undefined reference!
When I remove the anonymous namespace arround the class it compiles and runs! But why? Here is some example code that reproduces the situation:
main.cpp:
#include "notmain.h"
#include "theclass.h"
A *ourA=NULL;
int main()
{
theA = new A();
theA->dostuff(1024);
sunshine sun;
sun.Init();
}
notmain.cpp:
#include "notmain.h"
#include "theclass.h"
void sunshine::Init()
{
theA->dostuff(127);
}
notmain.h:
#ifndef NOTMAIN_H_
#define NOTMAIN_H_
class sunshine
{
public:
void Init();
};
#endif
theclass.h:
#ifndef THECLASS_H_
#define THECLASS_H_
#include <stdio.h>
#define theA ourA
namespace
{
class A
{
public:
void dostuff(int b)
{
a = b;
printf("Hello: %d\n",a);
}
private:
int a;
};
}
extern A *ourA;
#endif
Compiler/Linker Output:
09:09:57 ** Incremental Build of configuration Debug for project Testo **
Info: Internal Builder is used for build
g++ -O0 -g3 -Wall -c -fmessage-length=0 -o main.o "..\main.cpp"
g++ -O0 -g3 -Wall -c -fmessage-length=0 -o notmain.o "..\notmain.cpp"
g++ -o Testo.exe notmain.o main.o
notmain.o: In function ZN8sunshine4InitEv':
D:\Projekte\Testo\Debug/../notmain.cpp:6: undefined reference toourA'
collect2.exe: error: ld returned 1 exit status
09:09:57 Build Finished (took 702ms)
Removing that namespace fixes the problem but why does it compile, link, work in KEIL? Can anyone explain this to me?

I would suggest that that is an abuse of the anonymous namespace feature. It does exactly the opposite of what you are trying to achieve.
Anonymous namespaces are used to localise a definition to a single translation unit. If you place one in a header file, then include that header in multiple translation units, that will result in multiple independent definitions in your code.
What is happening here VC++ is that a global ourA has been instantiated as a pointer to one local definition of A defined in main.cpp, then later that local definition is no longer visible but is distinct from the currently visible local version in notmain.cpp. The name mangling of ZN8sunshine4InitEv distinguishes between independent definitions, but name mangling is compiler defined, and I guess ARM's RealView compiler (used by uVision) has a different scheme that fails to spot this error.
It is unclear in fact what the result if this error is in RealView, but it cannot be correct or at least well defined.
RealView is in fact rather poor at issuing warnings that other compilers do normally, and is somewhat permissive when it comes to undefined behaviour I have found. It is always worth using another toolchain such as MinGW/GCC with -Werror -Wall or using a static analysis tool to clean up your code.
To solve this problem you should use an explicitly named namespace, or no namespace at all.

Related

No multiple definition error despite including source file in another and compiling both

Let's say I have 3 files:
Test.hh
#ifndef TEST_HH_
#define TEST_HH_
class Test
{
int test() const;
};
#endif /* TEST_HH_ */
Test.cc:
#include "Test.hh"
int Test::test() const
{
return 0;
}
main.cc:
#include "Test.cc"
int main()
{
return 0;
}
It does not compile (rather does not link), I understand why, I defined Test::test() in multiple translation units (in main.cc that includes Test.cc and in Test.cc):
g++ -Wall -g -std=c++17 -c main.cc -o main.o
g++ -Wall -g -std=c++17 -c Test.cc -o Test.o
g++ -o bin main.o Test.o
Test.o: In function `Test::test()':
Test.cc:12: multiple definition of `Test::test()'
main.o:Test.cc:12: first defined here
collect2: error: ld returned 1 exit status
Edit: This is NOT my issue, my issue is that with a seemingly identical situation, in a bigger project, the previous example produces a binary (i.e. compiles and links) when, as far as I understand it, it shouldn't. I will now describe the real case with a bit more details and how the problem suddenly arised when previously it was working fine (when it shouldn't have).
--
I am currently working on a large project (~2500 files), and while trying to use the "Test" class above, I ended up having a lot of "multiple definitions" errors at link time. To translate it to our example, it's like I had another class doing this:
OtherClass.hh
#include "Test.hh" // including or using forward declaration led to the same results
//class Test; forward declaration
class OtherClass
{
// Some stuff, whatever
};
I ended up finding that Test.cc was included in another source file (main.cc in my very simplified exemple though it was in another "someClass.cc" in my actual project). After including the header instead of the source, it compiled again. What's more surprising is that other classes had been using Test.hh the same way until then without any problems.
Since I was really surprised, I ended up doing a grep on all my files and found that another 2 source files had included other sources files as well.
WhateverClass.cc
#include "Test2.cc"
YetAnotherClass.cc
#include "Test3.cc"
All those files are compiled and contain function definitions yet the linker does not complain. I tried doing a compilation from scratch and it still worked.
So my question is: Why does this compile even though some source files include others and all of them are compiled ? And why did it suddenly stop working even though I just included the header of one of those source files just like other classes had been doing ? Is there a kind of "undefined behavior" for cases like this ?
If it is of any help, my project is using CMake. I tried compiling with ninja or Make with the same results.
I had a similar question before. So, here's what I learned- never include source file. Only include header files. Your error comes from including a source (.cc) file in your main. You should include Test.hh instead. Declare all your classes and functions in header, include that header to all the source files where the definitions and the calls are.

C++ static instance of a user-defined class results a double-call to constructor when compiled and linked in separate steps

So I have reduced the problem to a very simple program of an empty main() function and a very simple class as follows.
A.cpp
#include <iostream>
class A {
public:
A() {std::cout<<"Inside A()"<<std::endl;}
};
static A a;
test.cpp
#include "A.cpp"
int main() {}
Now consider 2 options for building this simple program into 2 different executables:
Generating program #1:
Compile with the following command (generate .o files from the .cpp files):
g++ -c test.cpp A.cpp
And then link with the following command:
g++ test.o A.o -o linkedTest
Generating program #2:
Compile and link at once with the following command:
g++ test.cpp -o test
So at this point we have 2 programs next to the source files (alongside the intermediate .o files): linkedTest and test.
Now, running the program test (command ./test) it will execute the constructor of the class A only once and print the text "Inside A()". In contrast, running the program linkedTest (command ./linkedTest) it will execute the constructor of the class A twice!
So my questions are : Why is this happening? Shouldn't the same compiler (at least) generate the same program out of the same source-code? What is exactly happening behind the stage and how to take control over it? Is this an anticipated compiler/linker behavior or it's a (un)known bug?
Any C++ gurus out there who could shed some light on this...?
For your reference, my GCC version is : gcc (Ubuntu 7.5.0-3ubuntu1~18.04) 7.5.0
Remember that static var are defined per-compile unit
In case of :
g++ -c test.cpp A.cpp
g++ test.o A.o -o linkedTest
the compiler create 2 obj each of one have his own static var A.
while by building only one obj :
g++ test.cpp -o test
you get one compilation unit and so one definition of A.
When you compile both test.cpp and A.cpp, you have two compilation units that both define a variable named a. Since that variable is declared as static, that is legal (otherwise you'd get an error about a being defined twice) and causes two independent variables to be defined with the same name. And since you get two variables, you also get two constructor calls.
When you only define test.cpp, there's only one compilation unit, only one a and thus only one constructor call.
PS: It's generally a bad idea to include source files into each other because it leads to issues like this.
It's unusual, and normally a bad idea, to #include a *.cpp file.
But you would get the same behavior if you used a header file like normal, and a second *.cpp file that includes it:
// A.hpp:
#ifndef TEST_CLASS_A_HPP
#define TEST_CLASS_A_HPP
#include <iostream>
class A {
public:
A() {std::cout<<"Inside A()"<<std::endl;}
};
static A a;
#endif
// A.cpp:
#include "A.hpp"
// and nothing else!
// test.cpp:
#include "A.cpp"
int main() {}
When compiling the program above in the normal way, there are two "translation units": one for A.cpp, which includes everything in A.hpp, and one in test.cpp, which also includes everything in A.hpp. Outside of any class or function, the keyword static means a definition has "internal linkage", so that it cannot be used from another translation unit, and if another translation unit defines something similar, it's defining a different object or function with the same name. So yes, the program has and automatically creates two objects both named a of type A.
Your original program which was made from both A.cpp and test.cpp which included A.cpp similarly had two translation units, each with its own object named a of type A. The version just compiling test.cpp had just the one translation unit, and one a object.

What is the correct way to compile multiple test sources with Catch2?

I have the following project structure:
test_main.cc
#define CATCH_CONFIG_MAIN
#include "catch2.hpp"
test1.cc
#include "catch2.hpp"
#include "test_utils.hpp"
TEST_CASE("test1", "[test1]") {
REQUIRE(1 == 1);
}
test2.cc
#include "catch2.hpp"
#include "test_utils.hpp"
TEST_CASE("test2", "[test2]") {
REQUIRE(2 == 2);
}
test_utils.hpp
#pragma once
#include <iostream>
void something_great() {
std::cout << ":)\n";
}
If I compile using something like clang++ -std=c++17 test_main.cc test1.cc test2.cc, the function something_great is defined in both test1.o and test2.o. This leads to an error like
duplicate symbol __Z15something_greatv in:
test1.cc.o
test2.cc.o
ld: 1 duplicate symbol for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)
In the Scaling Up section of the Catch2 documentation, they mention that in order to split up your tests you may want to
Use as many additional cpp files (or whatever you call your
implementation files) as you need for your tests, partitioned however
makes most sense for your way of working. Each additional file need
only #include "catch.hpp"
but in the examples section of the documentation I don't see a use case like mine. I read this blog post which describes three solutions which don't appeal to me: defining functions as macros, or making functions static or inline.
Is there another way to compile these files which yield a single executable with the main function defined by test_main.cc?
This actually has nothing to do with Catch or testing. When you #include a file in C++, it gets copy-pasted at the #include line verbatim. If you put free function definitions in headers, you would see this problem building your actual program, etc.
The underlying problem is that #include is not the same kind of import-a-module directive as is the equivalent directive (import, require, etc.) in most languages, which do the sane thing in a situation like this (confirm that the header is the same one we've already seen and ignore the repeated method definition).
The commenter that suggested you write inline is technically correct, in the sense that this will "solve your problem" because your compiler won't generate object code for the method multiple times. However, it doesn't really explain what's going on or address the underlying issue.
The clean solution is:
In test_utils.hpp, replace the method definition with a method declaration: void something_great();.
Create test_utils.cc with the definition of the method (which you currently have in the .hpp).
clang++ -std=c++17 test1.cc -c
clang++ -std=c++17 test2.cc -c
clang++ -std=c++17 test_main.cc -c
clang++ -std=c++17 test_utils.cc -c
clang++ -std=c++17 test1.o test2.o test_utils.o test_main.o
I also recommend you read this: What is the difference between a definition and a declaration?
Explicitly:
// test_utils.hpp
#pragma once
// This tells the compiler that when the final executable is linked,
// there will be a method named something_great which takes no arguments
// and returns void defined; the definition lives in test_utils.o in our
// case, although in practice the definition could live in any .o file
// in the final linking clang++ call.
void something_great();
And:
// test_utils.cpp
#include "test_utils.hpp"
#include <iostream>
// Generates a DEFINITION for something_great, which
// will get put in test_utils.o.
void something_great() { std::cout << "Hi\n"; }
It seems you are worried about "recompiling Catch" every time you make a change to a test. I hate to break it to you, but you are in C++ land now: you are going to be recompiling stuff pointlessly a lot. Header-only libraries like Catch MUST be "recompiled" to some extent when a source file including them changes, because for better or worse, if the source file or a header file included transitively from the source file includes catch2.hpp, then the source code of catch2.hpp will get parsed by the compiler when that source file is read.
After some experimentation, I found a reasonable solution which doesn't require you to fully recompile Catch any time you make a change to a test.
Define test_main.cc in the same way as before:
#define CATCH_CONFIG_MAIN
#include "catch2.hpp"
Add another .cc file, test_root which includes your test files as headers:
#include "test1.hpp"
#include "test2.hpp"
Change your test sources to headers:
test1.hpp
#pragma once
#include "catch2.hpp"
#include "test_utils.hpp"
TEST_CASE("test1", "[test1]") {
REQUIRE(1 == 1);
}
test2.hpp
#pragma once
#include "catch2.hpp"
#include "test_utils.hpp"
TEST_CASE("test2", "[test2]") {
REQUIRE(2 == 2);
}
Compile separately
clang++ -std=c++17 test_main.cc -c
clang++ -std=c++17 test_root.cc -c
clang++ test_main.o test_root.o
Where test_main.cc needs only be compiled once. test_root.cc will need to be recompiled whenever you change your tests and of course you must relink the two object files.
I will leave this answer unaccepted for now in case there are better solutions.

undefined reference error for g++ but not for gcc when using BSP library

I am making a parallel program for one of my courses. Now initially it was written in C and it all worked just fine. Then we changed it all to c++ and all of a sudden I get some error when I try to compile the program. I am using the package mcbsp (Multicore BSP) for the parallel part. Here is the program
#include <stdio.h>
#include <stdlib.h>
#include <mcbsp.h>
void sieve(){
return ;
}
main(int argc, int **arhv){
bsp_begin(5);
printf("%d\n",bsp_pid());
bsp_end();
return 0;
}
So I make a file aaa.c and aaa.cpp both with this content. Then when I type in the terminal
gcc aaa.c -MMD -g -I../bsp/include -L../bsp/lib -lmcbsp1.2.0 -lpthread
it compiles just fine and the program does as expected (print the id of the cores). However, when I type
g++ aaa.cpp -MMD -g -I../bsp/include -L../bsp/lib -lmcbsp1.2.0 -lpthread
it gives the following feedback
/tmp/ccH3uox9.o: In function `main':
/home/teun/Documents/C/BSP/Sieve/sieve/aaa.cpp:10: undefined reference to `bsp_begin(unsigned int)'
/home/teun/Documents/C/BSP/Sieve/sieve/aaa.cpp:11: undefined reference to `bsp_pid()'
/home/teun/Documents/C/BSP/Sieve/sieve/aaa.cpp:12: undefined reference to `bsp_end()'
collect2: error: ld returned 1 exit status
I have been stuck with this for about an hour now and it is really getting frustrating. I must admit that I have little experience in programming in c++ as I mostly use C. Does anyone know what is going wrong?
EDIT: The program I displayed is just a small working example that uses the BSP functionality.
The simple declaration int bsp_end(); is interpreted differently in C and C++. The reason is that in C++, you can overload functions, which requires that their parameters are included in the symbol name for the linker, see C++ name mangling for further info. Now, since the function is compiled with a C compiler but the declaration is given to a C++ compiler, the symbols don't match and you get linker errors.
As a solution, add extern "C" to the function declaration or maybe wrap the whole include:
extern "C" {
#include <mcbsp.h>
}
You need extern "C" around #include
extern " C" {
#include "c-header.h"
};
This is needed to stop the C++ name mangling

Link dynamic shared library in Linux - Undefined reference to function

I know there are many questions related to shared libraries on Linux but maybe because I'm tired of having a hard day trying to create a simple dynamic library on Linux (on Windows it would have taken less than 10 minutes) I can't find what happens in this case.
So, I am trying to create a library to be linked at build-time and used at run-time (not a static library, not a library to be embedded into the executable, in other words). For now it contains a simple function. These are my files:
1.
// gugulibrary.cpp
// This is where my function is doing its job
#include "gugulibrary.h"
namespace GuGu {
void SayHello() {
puts("Hello!");
}
}
2.
// gugulibrary.h
// This is where I declare my shared functions
#include <stdio.h>
namespace Gugu {
void SayHello();
}
3.
// guguapp.cpp
// This is the executable using the library
#include "gugulibrary.h"
int main() {
GuGu::SayHello();
return 0;
}
This is how I try to build my project (and I think this is what is wrong):
gcc -Wall -s -O2 -fPIC -c gugulibrary.cpp -o gugulibrary.o
ld -shared -o bin/libGugu.so gugulibrary.o
gcc -Wall -s -O2 guguapp.cpp -o bin/GuGu -ldl
export LD_LIBRARY_PATH=bin
This is saved as a .sh file which I click and execute in a terminal. The error I get when trying to link the library is this:
/tmp/ccG05CQD.o: In function `main':
guguapp.cpp:(.text.startup+0x7): undefined reference to `SayHello'
collect2: ld returned 1 exit status
And this is where I am lost. I want the library to sit in the same folder as the executable for now and maybe I need some symbols/definitions file or something, which I don't know how to create.
Thanks for your help!
In your C++ file, GuGu::SayHello is declared as a C++ symbol. In your header, you are wrapping it in an extern "C" block. This is actually undefined, as you aren't allowed to use C++ syntax (namespace) in that context. But my guess is that what the compiler is doing is ignoring the namespace and generating a C symbol name of "SayHello". Obviously such a function was never defined by your library. Take out the extern "C" bits, because your API as defined cannot be used from C anyway.
You are inconsistent with your GuGu, there are also Gugu's running around, this needs to be made consistent, then it works (At least on my computer are some Gugu's now)