I have a problem with a static library build with Xcode 4.6.2 using the LLVM Clang Compiler. The problem occurs only if I use the C/C++ Compiler flag visibility=hidden. The Linker reports me a duplicate symbol error. I will explain the setup in an easy scenario and I hope someone can explain why this happen.
Imagine I have two classes ClassA and ClassB which I compile into a static library myLib. As said above, I set the Compiler flag -fvisibility=hidden.
Then I have a project which creates an executable from a main.cpp which uses the myLib.
Here are the classes:
ClassA.h
#pragma once
#include <boost/exception/all.hpp>
struct my_error : virtual std::exception, virtual boost::exception {};
class ClassA
{
public:
explicit ClassA() {};
virtual ~ClassA() {};
virtual void doSomething();
};
ClassA.cpp
#include "ClassA.h"
void ClassA::doSomething()
{
BOOST_THROW_EXCEPTION( my_error() << boost::errinfo_api_function("doSomething") );
}
ClassB.h
#pragma once
#include "ClassA.h"
class ClassB
{
public:
explicit ClassB() {};
virtual ~ClassB() {};
virtual void doSomething();
};
ClassB.cpp
#include "ClassB.h"
void ClassB::doSomething()
{
BOOST_THROW_EXCEPTION( my_error() << boost::errinfo_api_function("doSomething") );
}
These two classes a build into my library without a problem. In my executable project which links the myLib I have the following main.cpp
main.cpp
#include <iostream>
#include "ClassA.h"
#include "ClassB.h"
int main(int argc, const char * argv[])
{
ClassA A;
ClassB B;
return 0;
}
The C++ flags:
The build results in the following errors:
duplicate symbol __ZTIPN5boost21errinfo_api_function_E in:
/Users/georg/Library/Developer/Xcode/DerivedData/ExceptionTest-dcnvciwqbwqvciaokkjjaqchftll/Build/Products/Debug/libExceptionLib.a(ClassA.o)
/Users/georg/Library/Developer/Xcode/DerivedData/ExceptionTest-dcnvciwqbwqvciaokkjjaqchftll/Build/Products/Debug/libExceptionLib.a(ClassB.o)
duplicate symbol __ZTSPN5boost21errinfo_api_function_E in:
/Users/georg/Library/Developer/Xcode/DerivedData/ExceptionTest-dcnvciwqbwqvciaokkjjaqchftll/Build/Products/Debug/libExceptionLib.a(ClassA.o)
/Users/georg/Library/Developer/Xcode/DerivedData/ExceptionTest-dcnvciwqbwqvciaokkjjaqchftll/Build/Products/Debug/libExceptionLib.a(ClassB.o)
ld: 2 duplicate symbols for architecture i386 clang: error: linker
command failed with exit code 1 (use -v to see invocation)
If I change the Compiler Flags to the following it works:
The problem is the boost::errinfo_api_function object, but I do not understand why?
I hope someone can help me.
Kind Regards
Georg
Related
I'm trying to write a small C++ inheritance program, that will contain virtual functions, headers, and 3 class, A, B:A, C:B, after compiling succeeds, the linker fails in the derived of a derived class, C.o, stating
relocation against `_ZTV26C' in read-only section `.text'
and
undefined reference to `vtable for C'
can anyone see what am i missing?
A.h
#ifndef A_H_
#define A_H_
#include <string>
#include <iostream>
using namespace std;
class A {
protected:
string name;
public:
A(string name);
virtual ~A();
virtual void justATest(){}
void justBecause();
virtual bool derivedTest(){}
};
#endif /* A_H_ */
A.cpp
#include "A.h"
A::A(string name) {this->name.assign(name);}
A::~A() {}
void A::justBecause(){}
B.h
#ifndef B_H_
#define B_H_
#include "A.h"
#include <string>
class B : public A{
public:
B(string name):A(name){}
virtual ~B(){}
bool derivedTest();
};
#endif /* B_H_ */
B.cpp
#include "B.h"
bool B::derivedTest()
{
return true;
}
C.h
#ifndef C_H_
#define C_H_
#include "B.h"
class C : public B{
public:
C(string name) :B(name){}
virtual ~C(){}
void justATest();
};
#endif /* C_H_ */
C.cpp
#include "C.h"
void C::justATest()
{
cout<< this->name;
}
main.cpp
#include "C.h"
int main(int argc, char* argv[]) {
C* c = new C("str");
return 0;
}
the exact make command, and the error message:
make all Building target: demo_proj Invoking: GCC C++ Linker g++ -o "ass5_demo" ./A.o ./B.o ./C.o ./main.o /usr/bin/ld: ./main.o: warning: relocation against _ZTV1C' in read-only section .text._ZN1CC2ENSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEE[_ZN1CC5ENSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEE]' /usr/bin/ld: ./main.o: in function C::C(std::__cxx11::basic_string<char, std::char_traits, std::allocator >)': /home/some_user/eclipse-workspace/demo_proj/../C.h:14: undefined reference to vtable for C' /usr/bin/ld: warning: creating DT_TEXTREL in a PIE
After many hours of debugging, and countless tries, with the same error message i found the answer.
This is C++ linker crooked way of telling me there is an unimplemented method in one of my classes.
adding to
c.h
bool derivedTest() override;
and to c.cpp
bool C::derivedTest(){return false;}
p.s another nice way of finding the problem is adding override after each message in the header file, the compiler is much clearer
I am having a compile issue with C++ Modules, OpenCV 4.5.5 in VS2022
I get C1001 "Internal Compiler Error"
Whats the best way to fix this?
ClassA.ixx:
module;
#include <opencv2/opencv.hpp>
#include "ClassB.h"
export module ClassA;
export class ClassA
{
public:
cv::Mat myMat_; // <- This line fails to compile
ClassB b_; // <- ok
};
main.cpp
import ClassA;
int main()
{
ClassA a;
return 0;
}
I have a problem of undetected dependencies in a project I'm creating with Visual 2019/CMake/ninja. For a demonstration of this problem I have created a small case with two classes ClassA and ClassB.
The .cpp file of ClassA is:
#include "ClassA.h"
#include "ClassB.h"
ClassA::ClassA()
{}
ClassA::~ClassA()
{}
void ClassA::callPrivateB()
{
ClassB toto;
toto.privateFct();
}
The .h file of ClassB is:
#pragma once
class ClassB
{
public:
ClassB();
~ClassB();
void privateFct();
};
And the main.cpp is:
#include <ClassA.h>
int main(int argc, char* argv[])
{
ClassA toto;
toto.callPrivateB();
return 0;
}
Note: ClassA.h, ClassB.cpp, and CMakeLists.txt are not added too do not put to many code.
I'm compiling this application. Everything works well. That is normal. Now, I'm changing the file ClassB.h to put privateFct private. Then I request to recompile the application. And the result is:
ninja: no work to do.
Generate all: OK.
So, the fact that ClassA.cpp depends of ClassB.h has not been detected by ninja? cmake? Visual?
Any idea on how to solve this problem?
I'm very new to C++, and I'm trying to use googlemock and googletest. I can't seem to get them to work even in simple examples so I'm sure there must be something simple I'm missing. I would really appreciate some help on this. I have a class Foo which has another class Bar as a dependency so I'm trying to mock this dependency out in tests. I'm sorry in advance, this seems like the simplest Dependency Injection example to me but it still spreads across 9 files! This is Bar:
// lib/bar.h
#ifndef BAR_H
#define BAR_H
class Bar {
public:
Bar(int baz);
virtual ~Bar() {};
int _baz;
};
#endif
With implementation:
// lib/bar.cpp
#include "bar.h"
Bar::Bar(int baz) : _baz(baz) {}
Here is the MockBar header:
// tests/mock_bar.h
#ifndef MOCK_BAR_H
#define MOCK_BAR_H
#include <gmock/gmock.h>
#include "../lib/bar.h"
class MockBar : public Bar {
public:
MockBar();
virtual ~MockBar() {};
};
#endif
And the implementation:
// tests/mock_bar.cpp
#include "mock_bar.h"
MockBar::MockBar() : Bar(0) {
}
So MockBar is just Bar with baz set to 0. Here is Foo:
// lib/foo.h
#ifndef FOO_H
#define FOO_H
#include "bar.h"
class Foo {
public:
Foo(Bar bar);
virtual ~Foo() {};
Bar _bar;
int getBaz();
};
#endif
// lib/foo.cpp
#include "foo.h"
Foo::Foo(Bar bar) : _bar(bar) {
}
int Foo::getBaz() {
return _bar._baz;
}
And here is my test:
// tests/test_foo.h
#ifndef TEST_FOO_H
#define TEST_FOO_H
#include <gtest/gtest.h>
#include "../lib/foo.h"
#include "mock_bar.h"
class FooTest : public ::testing::Test {
public:
FooTest();
Foo subject;
MockBar mock_bar;
virtual ~FooTest() {};
};
#endif
// tests/test_foo.cpp
#include "test_foo.h"
FooTest::FooTest() : mock_bar(), subject(mock_bar) {
}
TEST_F(FooTest, BazTest)
{
ASSERT_TRUE(subject.getBaz() == 0);
}
Finally, the main test function is:
// tests/main.cpp
#include <gtest/gtest.h>
#include <gmock/gmock.h>
#include "test_foo.h"
int main(int argc, char **argv) {
testing::InitGoogleMock(&argc, argv);
testing::InitGoogleTest(&argc, argv);
return RUN_ALL_TESTS();
}
When I compile this all together with:
g++ tests/main.cpp tests/test_*.cpp tests/mock_*.cpp lib/*.cpp -o test
-lgtest -lpthread -std=c++11
I get the error:
Undefined symbols for architecture x86_64:
"testing::InitGoogleMock(int*, char**)", referenced from:
_main in main-0b53fe.o
ld: symbol(s) not found for architecture x86_64
clang: error: linker command failed with exit code 1
I would really appreciate some help, please let me know if I can be more clear!
You are using parts from gmock but only linking gtest. Thats why InitGoogleMock() is undefined.
Replacing -lgtest with -lgmock should make it.
The reason: gtest is testing framework, gmock the mocking framework.
If you link gmock, its includes also gtest but not the other way round.
I did not realize in a .dll library object types that depends on things that happen at compile time can case problems until I read the question Could I ignore C4251 warning in this case? In deed, if the library compilation settings for the library and the program that uses the library are different, some errors can occur. Here is an example:
dll.h
#include <iostream>
#include <string>
using namespace std;
class __declspec(dllexport) HelloWorld
{
public:
#ifdef DTEST
int test;
#endif
HelloWorld();
};
dll.cpp
#include "dll.h"
HelloWorld::HelloWorld()
{
#ifdef DTEST
test=0;
#endif
}
exe.cpp
#include "dll.h"
#include <iostream>
using namespace std;
int main(void)
{
HelloWorld myworld;
return 0;
}
If I compile dll.h and dll.cpp to create dll.lib and dll.dll with the definition of DTEST but compile exe.cpp without the definition of DTEST. I will have a runtime check failure #2 error. Could some explain why I have this error. Thanks!
You have this error because DTEST is a preprocessor macro and you are not defining it consistently for all pieces of your program. It is completely removed by the time your code reaches the actual compiler, so the compiler won't catch the problem. If you define DTEST for dll.cpp but not for exe.cpp, then exe.cpp will look like this to the compiler:
(...contents of <iostream>...)
(...contents of <string>...)
using namespace std;
class __declspec(dllexport) HelloWorld
{
public:
HelloWorld();
};
(...contents of <iostream> again...)
using namespace std;
int main(void)
{
HelloWorld myworld;
return 0;
}
However, dll.cpp will look like this:
(...contents of <iostream>...)
(...contents of <string>...)
using namespace std;
class __declspec(dllexport) HelloWorld
{
public:
int test;
HelloWorld();
};
HelloWorld::HelloWorld()
{
test=0;
}
The problem here is dll.cpp and exe.cpp have two different ideas of what HelloWorld is: dll.cpp thinks it contains test, but exe.cpp thinks it doesn't. There is a runtime check that catches this mismatch, which is what you're seeing.
What the compiler sees is the results of preprocessor expansion.
In your example, the compiler sees:
class HelloWorld
{
public:
int test;
HelloWorld();
};
in dll.cpp, and
class HelloWorld
{
public:
HelloWorld();
};
in exe.cpp. Same class, two different definitions. That's
a violation of the one definition rule, which results in
undefined behavior.
This has nothing to do with the C4251 warning (which if
I understand correctly, only concerns linking between different
DLLs).