Linker error when using static members - c++

I'm using Qt 4.7 and Cmake 2.8.3 with g++ 4.2.1 on Mac OS X.
I'm getting a bizarre linker error when using static or global variables in one of my files.
Here's the error:
ld: duplicate symbol ColorTrail::calculateColorUniformLocation in CMakeFiles/GLBall.dir/src/DesktopMain.cpp.o and CMakeFiles/GLBall.dir/src/ColorTrail.cpp.o
collect2: ld returned 1 exit status
calculateColorUniformLocation is a static member of class ColorTrail... but its not even used in DesktopMain.cpp at all!
Here's what I've tried:
Renaming the variable doesn't fix the problem.
Moving the variable out of the class and just making it a plain global variable also doesn't fix it
The file ColorTrail.h:
#ifndef COLORTRAIL
#define COLORTRAIL 9
#include "GlobalConstants.h"
#include <vector>
using namespace std;
class ColorTrail
{
private:
//note that this is NOT a Q_OBJECT
static GLint calculateColorUniformLocation;
//omitted for brevity
};
GLint ColorTrail::calculateColorUniformLocation;
#endif
DesktopMain.cpp uses class ColorTrail, but not statically and never references the variable.
Anyone have any idea what could be wrong/had a similar problem with Qt?

You need to define the static variable in cpp file and not in header file. If you define it in header file, every cpp file which includes this header will get its own copy hence linker complains about duplicate symbols.

Static data members must be explicitly defined in exactly one compilation unit
See this link: http://www.parashift.com/c++-faq-lite/ctors.html#faq-10.12

Related

Referring to an object from custom library gives error: "pointer to incomplete class type is not allowed"

So in my Visual Studio solution I'm making a library and I have two Visual Studio projects, one for the library and one for the sandbox. In the library I'm trying to use forward declarations to create a class. What I'm simply doing in this example is creating a header file for my class, declaring std::string with the following forward declaration and creating a member pointer with that class.
Library project:
ClassFromLibrary.h
#pragma once
namespace std {
class string;
}
class ClassFromLibrary {
public:
ClassFromLibrary();
~ClassFromLibrary();
std::string* forwardDeclaredString;
};
ClassFromLibrary.cpp
#include "ClassFromLibrary.h"
#include <string>
ClassFromLibrary::ClassFromLibrary()
: forwardDeclaredString(new std::string("Hello, world!"))
{
}
ClassFromLibrary::~ClassFromLibrary()
{
}
Sandbox project
main.cpp
#include <Library/ClassFromLibrary.h>
#include <iostream>
int main()
{
ClassFromLibrary test;
std::cout <<
*test.forwardDeclaredString //Root of the problem
<< std::endl;
std::cin.get();
}
The problem
As I said earlier, the library project compiles perfectly. However, the error which I mentioned in the title shows up when the forward declared member variable is referenced in any file from the sandbox project. I have a larger project where I get the same error, and the reason I want to achieve this is because I am using other external libraries within my library project, and when I create applications with it I don't want to have to put all the library include directories in the project properties, only the one for my library.
Thanks in advance!
You know that putting names in namespace std makes program ill-formed (except for some cases?)? Well, know you know why. The bug you have is a symptom of undefined behavior.
In my test, the way you declared your forward declaration in std is not how it is actually declared in string header. Yet it's a same name, so now you have name conflict (you have it as soon as you include iostream, which includes string. This is what my compiler is telling me when I am try compile your code:
/opt/compiler-explorer/gcc-8.2.0/lib/gcc/x86_64-linux-gnu/8.2.0/../../../../include/c++/8.2.0/bits/basic_string.h:6628:17:
error: reference to 'string' is ambiguous
struct hash<string>
This is different from the error you put in the question, but since the behavior is undefined, anything can happen.

simple C++ code linker error [duplicate]

This question already has answers here:
What is an undefined reference/unresolved external symbol error and how do I fix it?
(39 answers)
Closed 5 years ago.
Im trying to run a very simple snippet of code. I've been getting a linker error. My code looks like this:
main.cpp -->
#include <iostream>
#include "Complex.h"
using namespace std;
int main()
{
Complex c1(1.0, 5.0); // this should create Complex object 1.0 + i5.0
return 0;
}
Complex.h -->
#include <iostream>
class Complex {
private:
double real;
double imaginary;
public:
Complex(double, double);
void setReal(double);
void setImaginary(double);
};
Complex.cpp -->
#include "Complex.h"
#include <cmath>
Complex::Complex(double x, double y) {
setReal(x);
setImaginary(y);
}
void Complex::setReal(double x) {
real = x;
}
void Complex::setImaginary(double x) {
imaginary = x;
}
The error I've been getting looks like this:
I have been trying to run my main for a while but I keep getting the linker error. I have no clue what's causing it. I would appreciate any suggestions.
Just do
g++ main-3.cpp complex.cpp
mind the filename main-3, this is inconsistent in your question.
You have to feed all cpp files you are using into the g++ commandline to tell g++ where the code for the functions defined in the header lies. Read up on .o files, static linking and understand what that means.
Here is a little guide I follow to understand file inclusion and other factors:
c++ compilation is moronically simple:
read .cpp file
replace every #include statement with the text of the specified file (just dump it in)
If the resulting text still has #include directives (now from the header files), goto step 2.
Compile the hughe messy blob into a ´.o´ object file, replace calls to functions with symbols and add to that file a table of known symbols and where they are defined.
if there are more .cpp files specified, start a new empty text blob. Goto step 1.
call the linker ´ld´ to link all object files together, replace symbols with the actual addresses.
Strictly speaking, above is a little bit of a lie nowadays and a lot is left out and no optimizations mentioned. But it is still a useful guide to the compiler's behaviour.
To use it to interpret your error:
Complex.h got dumped into your blob, via the #include in main.cpp , but Complex.cpp did not. g++ generated an internal temporary .o file for you that contained something along the lines of
PUT 1.0 on Stack
PUT 5.0 on Stack
JUMP Complex::Complex
... and ran the linker ´ld´ with that .o file.
ld Could not find the address of the symbol Complex::Complex,
it needs a memory address to jump to.
If you compile Complex.cpp as well, the resulting Complex.o will have a symbol table with, for example, this entry:
Complex::Complex = 0xaaff
The linker, given Complex.o can now replace the symbol in main.o with an address.
PUT 1.0 on Stack
PUT 5.0 on Stack
JUMP 0xaaff

Duplicate Symbols in object files:

I am trying to compile two .cpp files, (foo.cpp and bar.cpp) and build a shared object (project.so). But the compilation fails and (a part of) the error I am getting is:
....
duplicate symbol _n in:
foo.o
bar.o
ld: 5 duplicate symbols for architecture x86_64
clang: error: linker command failed with exit code 1(use -v to see
invocation)
make: *** [project.so] Error 1
ERROR: compilation failed for package ‘project’
My .cpp files have few common and uncommon header files, a few commonly and uncommonly named functions, and a set of commonly named variables:
foo.cpp
#include <iostream>
#include <fstream>
#include <vector>
#include <ctime>
#include <cmath>
size_t m1;
double k1=2.0;
std::vector<double> x,y;
std::vector<double> z;
size_t n,p;
void inputfoo(){...}
void output(){...}
bar.cpp
#include <iostream>
#include <fstream>
#include <vector>
#include <ctime>
#include <cmath>
#include "Eigen/Dense"
#include "Eigen/Cholesky"
size_t m2;
double k2=2.0;
std::vector<double> x,y;
std::vector<double> z;
size_t n,p;
void inputbar(){...}
void output(){...}
My attempt:
I am able to get lesser number of 'duplicate symbols' error if I differ the names of global variables in each .cpp files. That is, if I change the size_t m to size_t m1 in foo.cpp and size_t m2 in bar.cpp, i do not get this part in the error
duplicate symbol _m in:
foo.o
bar.o
So, now I can see that the 5 symbols in the errors are for x,y,z,n,p ( defined globally in each .cpp file)
Same goes if I differ the name of the commonly named functions. Previously, I would also get this part in the error,
duplicate symbol __Z4inputP4init3RNGPi in:
foo.o
bar.o
which directs me to the input(){...} function.
So, I changed the name of one of the commonly named function ( input (){..} ), to inputfoo and inputbar and the respective error went away.
Now, I am sure i will be able to compile these two successfully if i make the names unique in each file. However, I cant change the x,y,z,n,p because they are numerous in these files and I have many more files to work with which have common named functions and variables.
Can anyone please explain it to me what is happening here and how to fix it? I would really like to know what is causing this. I tried reading from previous posts, 'Understanding the origin of a linker duplicate symbol error ' but I don't think it is a header related problem.
Thank you so much.
The example is incomplete, which makes it hard to comment.
But let me make a guess: you have globals in both files and they are visible across both. That is a design error. You can either
make them local to each file if their state is not shared, use static for that
make them shared by declaring one file only and using extern in the other.
But the error you quote is different and we don't know anything about your input::init()...
Also, I also see nothing related to Rcpp here, so wht add the tag for it?

C++ Undefined reference errors to the constructors and destructors of the classes which are inside a shared library

Ok, I am very new in C++ development. This question may be silly but I can not find its response in any tutorial, book, question/response. It would be great if somebody can kindly explain it to me.
I have 1 header-source pair inside of a shared library libdummy.so:
This is dummy.h:
class dummy
{
public:
~dummy();
dummy();
bool dosomething(int a);
};
and this is dummy.cpp:
#include "dummy.h"
dummy::dummy()
{
//some assignments here
clear();
}
dummy::~dummy()
{
clear();
}
bool dummy::dosomething(int a)
{
// do something here
return true;
}
EDIT: I tell you above the sample codes of dummy.h and dummy.cpp but these files are not in my hand. They are packed inside the library libdummy.so. I have only the libdummy.so shared library file in the hand.
And I have a client to access my shared library.
client.h is here:
#include "dummy.h"
class client
{
public:
void myownjob();
dummy thingy;
//and some functions here
};
and finally this is the client.cpp:
#include "client.h"
void client::myownjob()
{
thingy.dosomething(1);
}
Now my problem is; when I try to compile this code, I get undefined reference errors to the constructor and destructor:
error: undefined reference to 'dummy::~dummy()'
error: undefined reference to 'dummy::dosomething(int)'
error: undefined reference to 'dummy::dummy()'
EDIT: The dummy.h and dummy.cpp are inside libdummy.so. I have only 3 files in the hand: libdummy.so, client.h and client.cpp.
That's why;
I can not delete ~dummy(); and dummy(); in the dummy.h to let the compiler creating them automatically. Because dummy.h is inside the libdummy.so shared library. It is not directly editable.
I can not do some braceleted empty definitions like ~dummy(){} and dummy(){} in the dummy.h. Because dummy.h is inside the libdummy.so shared library. It is not directly editable.
I can not include dummy.cpp to SRC_FILES line of my makefile. Because dummy.cpp is inside libdummy.so shared library. It is not a seperate file.
I think this is a very simple/beginner problem, but I can not find its response anywhere. What I have to do to use a class which is inside a shared library, in C++, when I get undefined reference errors to the constructors and destructors?
Thanks in advance.
I don't know about any NDK, but this error is a linking error - where you don't provide the library at link time (even though it's a dynamic library, you have to provide it when linking)
Normally I'd tell you to compile + link like this:
g++ client.cpp -ldummy
(-ldummy links with libdummy.so)
but given you're using some makefile you're not familiar with, I don't really know how you should do it. I can guess though:
Apparently you have a field named SRC_FILES. A quick (and incomplete) google suggest you have a field named LOCAL_LDLIBS. If so try setting this:
LOCAL_LDLIBS = -ldummy
Or, if the libdummy.so file isn't in your standard path:
LOCAL_LDLIBS = -L/dummy/file/path -ldummy
(/dummy/file/path is obviously the path of your dummy library)
Note that depending on your configuration, you might need to add the -L even if the file is in your working directory.
please compile both the file.. If you are using linux , than
g++ client.cpp dummy.cpp

MOC adding namespace to class names

I have this very strange problem while compiling the project.
MOC seems to be adding a namespace to the class name being moc'ed, although it's not mentioned anywhere in the file/class.
The namespace, however, exists in a library which I use, but it's hidden far away in the header files and I don't use it in the UI files. This is what MOC generates:
const QMetaObject SmpTl::CaptureController::staticMetaObject = {
{ &QObject::staticMetaObject, qt_meta_stringdata_SmpTl__CaptureController,
qt_meta_data_SmpTl__CaptureController, 0 }};
The SmpTl namespace is not mentioned anywhere in the declaration of CaptureController, but it appears in the MOC-generated .cpp file.
I'm using Visual Studio with the QT integration.
I also ran into this problem. I had code that looked like this:
namespace foo {
#ifdef _WIN32
... // This code was fine
#else
#error Not Supported
#endif
}
This confused MOC into thinking namespace foo never closed. Apparently, it didn't know _WIN32 was defined, and got tripped up by the fact that I forgot to put quotes around the error message. Changing it to:
#error "Not Supported"
fixed my problem.
SmpTl is the namespace CaptureController is defined in, as it was found by MOC.
The Q_OBJECT macro expands into the declaration of the staticMetaObject-variable inside your class definition (among other things it expands into). The MOC-file contains the definition of that variable.
If this is not correct, please post your Qt version and a stripped down version of your header-file.