I have two .so files and I am trying to call a parameterized constructor from one .so to the other. And I am getting a linker error. Here is the piece of code.
ABC.h
class ABC
{
ABC();
ABC(int i);
};
ABC.cpp
ABC::ABC()
{
//do something
}
ABC::ABC(int i)
{
//do something.
}
XYZ.cpp
#include "ABC.h"
void XYZ1()
{
ABC abc(); // this passes
}
void XYZ1(int i)
{
ABC abc(i); // This results in linker error when I run XYZ's executable
}
void main()
{
XYZ1();
}
Please note that I am using netbeans IDE.
I have noticed that parameterized constructor results in the error, default constructor doesn't throw any error. Is there any setting which I need to make am in the netbeans IDE.
Your constructor is private, thus it can't be invoked
I found out the problem, XYZ.so file was looking for ABC.so in the wrong location and thats the reason it was not able to link it properly. The reason why it was looking in some other location was because a path was set in "LD_LIBRARY_PATH", in this path a different version of ABC.so was present.
Thanks for your help.
Related
I want to use Visual Studio's Test Explorer to run my Google Tests. When I create a console project and add a default Google Test project, and build the solution, it finds the tests as intended.
Now I want to create my own class, where everything is set up in the header file.
class foo
{
public:
foo() : the_count(0) {}
~foo() = default;
void count_plus() { the_count++; };
int get_count() { return the_count; };
private:
int the_count;
};
Then I modify my test.cpp file (the default file created by Visual Studio's Google Test project) to make use of my new class.
#include "pch.h"
#include <iostream>
#include "..\ConsoleApplication2\foo.h"
class tester : public testing::Test {
public:
foo bar;
void SetUpTestSuite() {
std::cout << "Setup..\n";
}
void TearDownTestSuite() {
std::cout << "Teardown..\n";
}
};
TEST_F(tester, TestFixture1)
{
EXPECT_EQ(bar.get_count(), 0);
bar.count_plus();
EXPECT_EQ(bar.get_count(), 1);
}
Building this solution also automatically detects the tests and runs them succesfully.
Now it gets interesting... When I move my implementation of foo to a .cpp file.
foo.h
class foo
{
public:
foo();
~foo() = default;
void count_plus();
int get_count();
private:
int the_count;
};
foo.cpp
#include "foo.h"
foo::foo()
{
the_count = 0;
}
void
foo::count_plus()
{
the_count++;
}
int
foo::get_count()
{
return the_count;
}
And then I build the solution, I initially get a linker error complaining about unresolved externals.
However, if I change the test project's linker settings to point to the other project like so:
Properties -> Linker -> Input -> Additional Dependencies -> add $(SolutionDir)ConsoleApplication2\$(IntDir)*.obj
which I got from this answer, I can succesfully build the project.
However, after I finish building the project, I'm no longer able to see or run my tests.
Am I doing something wrong here? Or is Visual Studio just broken?
I figured it out. The project which generates the object files cannot have a main() function, as this overrides Google Test's main() function.
I solved it by:
Creating an empty project (with no main()) which contains all my source code and set this project's Configuration Type as Static library (.lib).
Creating a console application project (or whatever suits your needs) which contains my main() entry point. In this project, I add a reference to my .lib project.
Create a Google Test project. In this project, I also add a reference to my .lib project.
Set the project in step two as the Startup project.
Now when you want to run your code, it will run it from your one entry point, but grab the source from .lib project and your Google Test project will also grab this .lib file, detecting all your tests.
I'm trying to use Gradle (5.6.2) to build a basic C++ library, and cannot figure out what is going wrong here. I started out using Gradle init to create the basic structure... here's my build.gradle:
plugins {
// Apply the cpp-library plugin to add support for building C++ libraries
id 'cpp-library'
// Apply the cpp-unit-test plugin to add support for building and running C++ test executables
id 'cpp-unit-test'
}
// Set the target operating system and architecture for this library
library {
targetMachines.add(machines.macOS.x86_64)
dependencies {
implementation files('/usr/local/lib/libjsoncpp.a') // used by classA
}
}
tasks.withType(CppCompile).configureEach {
compilerArgs.add "-std=c++11"
compilerArgs.add "-w"
}
The source tree looks like this:
src/main/cpp -> classA.cpp classB.cpp classB.hpp hello.cpp
src/main/public -> classA.hpp cppd.h cpplib.h
src/test/cpp -> classATest.cpp hello_test.cpp
hello.cpp, cppd.h, cpplib.h, and hello_test.cpp all came from the 'gradle init' and aren't actually used.
classA calls a few methods in classB. classB only depends on standard libraries.
classB has a public method classB::method1() that calls two private methods classB::method2() and classB::method3()
When I build, I get a linker error that it can't find classB::method2() or classB::method3(). I checked the method signatures and they all match up (same number and type of arguments in classB.hpp, classB.cpp, and in the linker error message).
I've scoured the Gradle documentation and Googled everything I can think of, tried several variations on the build.gradle file, and... I don't understand why the linker can't find methods in the same CPP file??
Building with Clang 11.0 on MacOS 10.14.6 in case it matters...
Also for reference, here's the relevant bits of the header file:
class classB {
public:
method1();
private:
string& method2(const string& s, bool b);
int method3(uint16_t* b, const string& s);
}
And the methods from the cpp file:
string& method2(const string& s, bool b) {
// blah
}
int method3(uint16_t* b, const string& s) {
// blah
}
OH MY GOODNESS! Just... Nevermind. You know how sometimes posting the question itself is enough to make the problem obvious?
For the record, of course what's missing is the class identifyer-thing (sorry, can't recall the term, I'm coming back from Java) on the front of the method names in the CPP file. They should be:
string& classB::method2(const string& s, bool b) {
// blah
}
int classB::method3(uint16_t* b, const string& s) {
// blah
}
Without the class identifyer-things, the linker doesn't realize they are member functions, and doesn't make the connection.
I'm trying to declare an object from a class in another file. I have added the #include "transfer.h" into my metadata.cpp file, but I'm getting the following error:
metadata.o: In function `importMetadata':
metadata.cpp:(.text+0x81): undefined reference to A::B::C::Transfer::Transfer()'
metadata.cpp:(.text+0x81): undefined reference to A::B::C::Transfer::~Transfer()'
And Transfer is defined with in transfer.h
namespace A{
namespace B{
namespace C{
class Transfer {
public:
Transfer();
~Transfer();
int copydata();
... more code goes here.
};
}
}
}
The file transfer.cpp looks like this:
Transfer::Transfer(){
}
Transfer::~Transfer(){
}
I'm also doing an using namespace A::B::C; on the header of the metadata.cpp file. Could someone please help me on that?
In the function int importMetadata() in metadata.cpp I'm declaring Transfer transfer; so in metadata.cpp I'm doing 'transfer.copydata();`
Since you have linker error and not a compiler error this tells you that your #include statement is doing what you want and the compiler recognizes the Transfer class and its constructor. The error occurs when the linker tries to find a reference to the implementation of the Transfer::Transfer() function in one of the .o or .lib files its told to link but cannot find it.
It's likely you have a transfer.cpp to go along with the transfer.h and this file is missing the implementation of the Transfer constructor and destructor. This could be because the functions are missing altogether or have been accidentally defined with a different signature.
So transfer.cpp should look something like:
A::B::C::Transfer::Transfer()
{
}
A::B::C::Transfer::~Transfer()
{
}
Another possibility is that you are trying to link the implementaiton of transfer from a library. In this case you would need to tell your linker to use the .lib file as input. The syntax for this will depend on the compiler you are using.
Hopefully you left out part of your transfer.cpp file, but in case you didnt it should define the namespace to match your header file like such:
namespace A{
namespace B{
namespace C{
Transfer::Transfer(){
}
Transfer::~Transfer(){
}
}
}
}
In case you have fully defined the namespaces, either inline or as above, you'll want to make sure you have the transfer.cpp file included in your project. Seems like the linker is unable to find your source file.
Greetings,
I'm having a weird seg fault problem. My application dumps a core file at runtime. After digging into it I found it died in this block:
#include <lib1/c.h>
...
x::c obj;
obj.func1();
I defined class c in a library lib1:
namespace x
{
struct c
{
c();
~c();
void fun1();
vector<char *> _data;
};
}
x::c::c()
{
}
x::c::~c()
{
for ( int i = 0; i < _data.size(); ++i )
delete _data[i];
}
I could not figure it out for some time till I ran nm on the lib1.so file: there are more function definitions than I defined:
x::c::c()
x::c::c()
x::c::~c()
x::c::~c()
x::c::func1()
x::c::func2()
After searching in code base I found someone else defined a class with same name in same namespace, but in another library lib2 as follows:
namespace x
{
struct c
{
c();
~c();
void func2();
vector<string> strs_;
};
}
x::c::c()
{
}
x::c::~c()
{
}
My application links to lib2, which has dependency on lib1. This interesting behavior brings several questions:
Why would it even work? I would expect a "multiple definitions" error while linking against lib2 (which depends upon lib1) but never had such. The application seems to be doing what's defined in func1 except it dumps a core at runtime.
After attaching debugger, I found my application calls the ctor of class c in lib2, then calls func1 (defined in lib1). When going out of scope it calls dtor of class c in lib2, where the seg fault occurs. Can anybody teach me how this could even occur?
How can I prevent such problems from happening again? Is there any C++ syntax I can use?
Forgot to mention I'm using g++ 4.1 on RHEL4, thank you very much!
1.
Violations of the "one definition rule" don't have to be diagnosed by your compiler. In fact, they are often only going to be known at link time when you link multiple object files together.
At link time, the information about the original class definitions may not exist any more (they are not needed after the compiler step) so having multiple definitions of a class is typically not easy to flag to the user.
2.
Once you have two distinct definitions pretty much anything can happen, you are in the territory of undefined behaviour. Whatever happens, it's a possible outcome.
3.
The most sensible thing to do is to communicate with the other members of your team. Agree who's going to use which namespaces and you won't get these problems. Otherwise, you point a documentation tool or static analysis tool over your entire project. Many such tools will be able to diagnose multiple inconsistent definitions of classes.
Just a guess but I don't see any using namespace x; so perhaps it used one namespace instead of the other?
With the advent of templates it became necessary to allow multiple definitions of a body of code with the same name; there was no way for the compiler to know if the same template code had already been generated in another compilation unit i.e. source file. When the linker finds these duplicates, it assumes they are identical. The burden is on you to make sure that they are - this is called the One Definition Rule.
On the linker level this is library interpositioning. The effective symbol bound unfortunately depends on the order of object files on linker command line (this is, sigh, historical).
From what you describe it looks that lib1 comes first in linker argument list and lib2 comes second and interposes on symbols from lib1. This explains the calls to constructors and destructors from the lib2 but calls to func1 from lib1 (since there's no func1-derived symbol in lib2, so there's no "hiding", the call is bound to lib1.)
The solution to this particular problem is to reverse the order of libraries on the linker invocation command.
There's lots of answers about the one definition rule. However, to me, this looks a lot more like a missing copy constructor.
To elaborate:
If the copy constructor is called on your object, then you will get a memory leak. This is because delete will be called on the same set of pointers twice.
namespace x
{
struct c
{
c() {
}
~c() {
for ( int i = 0; i < _data.size(); ++i )
delete _data[i];
}
c(const c & rhs) {
for (int i=0; i< rhs.size(); ++i) {
int len = strlen(rhs[i]);
char *mem = malloc(len + 1);
strncpy(mem, rhs[i], len + 1);
_data.push_back(mem);
}
void fun1();
vector<char *> _data;
};
}
I'm setting up a C++ project, on Ubuntu x64, using Eclipse-CDT. I'm basically doing a hello world and linking to a commerical 3rd party library.
I've included the header files, linked to their libraries, but I still get linker errors. Are there some possible problems here other than the obvious (e.g. I am 99% sure I'm linking to the correct library).
Is there a way to confirm the static libraries I am linking to are 64bit?
Is there a way to confirm that the library has the class (and methods) I am expecting it to have?
Eclipse says:
Building target: LinkProblem
Invoking: GCC C++ Linker
g++ -L/home/notroot/workspace/somelib-3/somelib/target/bin -o"LinkProblem" ./src/LinkProblem.o -lsomelib1 -lpthread -lsomelib2 -lsomelib3
./src/LinkProblem.o: In function `main':
/home/notroot/workspace/LinkProblem/Debug/../src/LinkProblem.cpp:17: undefined reference to `SomeClass::close()'
./src/LinkProblem.o: In function `SomeOtherClass':
/home/notroot/workspace/somelib-3/somelib/include/sql/somefile.h:148: undefined reference to `SomeClass::SomeClass()'
/home/notroot/workspace/somelib-3/somelib/include/sql/somefile.h:148: undefined reference to `vtable for SomeOtherClass'
/home/notroot/workspace/somelib-3/somelib/include/sql/somefile.h:151: undefined reference to `SomeClass::~SomeClass()'
./src/LinkProblem.o: In function `~SomeOtherClass':
/home/notroot/workspace/somelib-3/somelib/include/sql/somefile.h:140: undefined reference to `vtable for SomeOtherClass'
/home/notroot/workspace/somelib-3/somelib/include/sql/somefile.h:140: undefined reference to `SomeClass::~SomeClass()'
/home/notroot/workspace/somelib-3/somelib/include/sql/somefile.h:140: undefined reference to `SomeClass::~SomeClass()'
collect2: ld returned 1 exit status
make: *** [LinkProblem] Error 1
This linker error usually (in my experience) means that you've overridden a virtual function in a child class with a declaration, but haven't given a definition for the method. For example:
class Base
{
virtual void f() = 0;
}
class Derived : public Base
{
void f();
}
But you haven't given the definition of f. When you use the class, you get the linker error. Much like a normal linker error, it's because the compiler knew what you were talking about, but the linker couldn't find the definition. It's just got a very difficult to understand message.
Assuming those methods are in one of the libs it looks like an ordering problem.
When linking libraries into an executable they are done in the order they are declared.
Also the linker will only take the methods/functions required to resolve currently outstanding dependencies. If a subsequent library then uses methods/functions that were not originally required by the objects you will have missing dependencies.
How it works:
Take all the object files and combine them into an executable
Resolve any dependencies among object files.
For-each library in order:
Check unresolved dependencies and see if the lib resolves them.
If so load required part into the executable.
Example:
Objects requires:
Open
Close
BatchRead
BatchWrite
Lib 1 provides:
Open
Close
read
write
Lib 2 provides
BatchRead (but uses lib1:read)
BatchWrite (but uses lib1:write)
If linked like this:
gcc -o plop plop.o -l1 -l2
Then the linker will fail to resolve the read and write symbols.
But if I link the application like this:
gcc -o plop plop.o -l2 -l1
Then it will link correctly. As l2 resolves the BatchRead and BatchWrite dependencies but also adds two new ones (read and write). When we link with l1 next all four dependencies are resolved.
Qt C++ will show this error when you change a class such that it now inherits from QObject (ie so that it can now use signals/slots). Running qmake -r will call moc and fix this problem.
If you are working with others via some sort of version control, you will want to make some change to your .pro file (ie add/remove a blank line). When everyone else gets your changes and runs make, make will see that the .pro file has changed and automatically run qmake. This will save your teammates from repeating your frustration.
The problem for me turned out to be pretty obscure. My class looked like this:
//-----------------------------------------
// libbase.h
class base {
public:
base() { }
virtual ~base() { }
virtual int foo() { return 0; }
};
//-----------------------------------------
//-----------------------------------------
// libbase.cpp
#include "libbase.h"
//-----------------------------------------
//-----------------------------------------
// main.h
class derived : public base {
public:
virtual int foo() ;
};
//-----------------------------------------
//-----------------------------------------
// main.cpp
int main () {
derived d;
}
//-----------------------------------------
The problem is in the linker. My header file went in a library somewhere, but all the virtual functions were declared 'inline' in the class declaration. Since there was no code using the virtual functions (yet), the compiler or linker neglected to put actual function bodies in place. It also failed to create the vtable.
In my main code where I derived from this class, the linker tried to connect my class to the base class and his vtable. But the vtable had been discarded.
The solution was to declare at least one of the virtual functions' bodies outside the class declaration, like this:
//-----------------------------------------
// libbase.h
class base {
public:
base() { }
virtual ~base() ; //-- No longer declared 'inline'
virtual int foo() { return 0; }
};
//-----------------------------------------
//-----------------------------------------
// libbase.cpp
#include "libbase.h"
base::~base()
{
}
//-----------------------------------------
In regards to problems with Qt4, I couldn't use the qmake moc option mentioned above. But that wasn't the problem anyway. I had the following code in the class definition:
class ScreenWidget : public QGLWidget
{
Q_OBJECT // must include this if you use Qt signals/slots
...
};
I had to remove the line "Q_OBJECT" because I had no signals or slots defined.
I had this error message. The problem was that I declared a virtual destructor in the header fileļ¼ but the virtual functions' body was actually not implemented.
This error will also occur when we simply declare a virtual function without any definition in the base class.
For example:
class Base
{
virtual void method1(); // throws undefined reference error.
}
Change the above declaration to the below one, it will work fine.
class Base
{
virtual void method1()
{
}
}
In my case the problem occured when i forgot to add the =0 on one function in my pure virtual class. It was fixed when the =0 was added. The same as for Frank above.
class ISettings
{
public:
virtual ~ISettings() {};
virtual void OKFunction() =0;
virtual void ProblemFunction(); // missing =0
};
class Settings : ISettings
{
virtual ~Settings() {};
void OKFunction();
void ProblemFunction();
};
void Settings::OKFunction()
{
//stuff
}
void Settings::ProblemFunction()
{
//stuff
}
I stumbled across the issue now, too. The application defined a pure virtual interface class and a user-defined class provided through a shared lib was supposed to implement the interface. When linking the application, the linker complained that the shared lib would not provide vtable and type_info for the base class, nor could they be found anywhere else.
Turned out that I simply forgot to make one of the interface's methods pure virtual (i.e. omitted the " = 0" at the end of the declaration. Very rudimentary, still easy to overlook and puzzling if you can't connect the linker diagnostic to the root cause.
I had this error message when trying "hello world" like things with Qt. The problems went away by correctly running the qt moc (meta object compiler) and compiling+including these moc-generated files correctly.
If you have a base class with pure virtual function, make sure your base class constructor and destructor has body otherwise linker fails.
I put this for future visitors:
if you are receiving the error on creating an Exception object, then the cause of it probably is a lack of definition for what() virtual function.