please help me, I have a strange problem which i can't sort out in any way.
Premise: I'm using visual c++ 2005 on windows 7 x64, and I'm sure that my code isn't fatally flawed because with g++ under Linux it runs nicely.
I am developing an application which uses a static library also developed by me.
In the link phase of the application i get two mysterious LNK2019 errors.
This is the header of one of the classes of the library:
namespace sulfur
{
class Quark
{
public:
... various methods
void addAccel(const Vec2 &a);
... various methods
private:
... various data
};
}
Obviously in the cpp file i provide an implementation for addAccel with exactly the same signature.
When I try to link the application with the library, ALL the other member functions are found, except for addAccel.
The linker searches for the symbol "?addAccel#Quark##QAEXABV?$TemplateVec2#M#Atlax###Z"
while in the .lib file there is (which i found using dumpbin) "?addAccel#Quark#sulfur##QAEXABV?$TemplateVec2#M#Atlax###Z". The only difference here is that the linker searches for a mangled name without the namespace part and I don't know why.
I've tried to change name, position, calling convention and signature of the metod but to no avail, always getting the same error.
The second error is very similar. I have another header in the library:
namespace sulfur
{
class Cluster
{
...
Quark *addQuark(sulfur::Feature feat, float x, float y, float m=0.1f, float aF=0.01f);
...
};
}
and a correct implementation file is provided. Like before, all the other methods are linked properly, but not addQuark.
The linker searches for "?addQuark#Cluster#sulfur##QAEPAVQuark##W4Feature#2#MMMM#Z"
but in the library there is "?addQuark#Cluster#sulfur##QAEPAVQuark#2#W4Feature#2#MMMM#Z".
This time the difference is the absence of the first '2' between the '#' in the version which the compiler searches for.
This isn't the first time that I build this application with visual studio and it has always linked ok except for this time with the last changes.
I don't have any clue,
thank you in advance
Where and how is the void addAccel(const Vec2 &a); function implemented? Are you sure that you are not missing Quark:: prefix on the implementation of the function?
Well, I've just solved the issue.
There where two erroneous forward declarations (outside of the namespace) of class Quark and class Cluster. For some reason g++ was ok with that, while VC++ was right to complain about it.
Thank you anyway.
Related
I have one big project in Eclipse, which contains multiple nested projects. Each one of those nested projects is in a separate folder and is compiled and linked separately. At the end, each one of them outputs a separate static library. Then there are few executables which are linked against those static libraries. In two of these projects I have two classes with the same name and same constructor arguments, but they have different implementations and also different extra members. Both classes are in the same namespace. After I compile each project I use the static libraries which they have created for a separate executables. Each executable is linked against the correct class, they don't mix implementations. Everything seems to work fine.
The problem is that when I compile one of the classes, the compiler gives me an error that I haven't initialized some member variables, which actually belong to the other class. During compilation those classes don't have an access to each other - they don't include the other one or they don't include headers, which then include the other one. They are in separate projects, in separate folders and are compiled separately. How is then possible that when compiling the first class the compiler somehow looks for the definition of the second class and gives me an error that I haven't initialized a member from it? Since I am using Eclipse and my projects' structure is like this: Main C++ Project (which is not compiled) holds the other C++ projects as nested projects (which are compiled separately) inside it - is it possible that this is something related to Eclipse?
Am I violating the One Definition Rule, since my classes are in separate projects and they are compiled in separate compilations, only having some common header files and no other connection between them? And if so, how is it possible that the compiler catches such an issue but it is still able to get the correct class definition? Because for sure it gets it right and everything works fine.
So my problem is the warning that the compiler gives me, because I have to clean all compilation warning before shipping the code. The code itself works fine.
Best Regards
=== Update After Comments ===
First of all, apologies for not being clear.
Here is an image of the whole Project structure (I have changed the names obviously :) ):
The structure of my project
I have the MainProject project, which acts as a container for the other projects. I don't build it. In nested1 I have projects which make static libraries, which I then link with the Executable1 and Executable2. In nested2 I have other projects which again make static libraries, which I then link with the Executable3.
I have the MyFooBar class in both nested1 and nested2. Here is the code for both of them
// nested1/StaticLib5/MyFooBar.hpp
namespace foo
{
namespace bar
{
class MyFooBar : public FooBar
{
public:
MyFooBar(int a, int b, double c);
// Getters and Setters
// Other user-defined functions
private:
int memA;
int memB;
double memC;
int memDiff1;
};
}
}
// nested2/StaticLib9/MyFooBar.hpp
namespace foo
{
namespace bar
{
class MyFooBar : public FooBar
{
public:
MyFooBar(int a, int b, double c);
// Getters and Setters
// Other user-defined functions
private:
int memA;
int memB;
double memC;
int memDiff2;
char memDiff3;
};
}
}
// nested1/StaticLib5/MyFooBar.cpp
namespace foo
{
namespace bar
{
MyFooBar::MyFooBar(int a, int b, double c) :
memA{a}, memB{b}, memC{c}, memDiff1{0}
{
}
}
}
// nested2/StaticLib9/MyFooBar.cpp
namespace foo
{
namespace bar
{
MyFooBar::MyFooBar(int a, int b, double c) :
memA{a}, memB{b}, memC{c}, memDiff2{0}, memDiff3{0}
{
}
}
}
Executable1 and Executable2 don't use any of the libraries in nested2. Executable3 uses the only the static library StaticLib1 nested1.
Non of the Executables is linked to both StaticLib5 and StaticLib9. Also, I don't get an error during the linking of the executables, I get warning when compiling any of the MyFooBar classes. The warning says:
Member memDiff2 was not initialized in this constructor
The only thing that might be common for both classes is one header, where I have a class forward declaration and some typedefs, which I don't use in the class itself.
class MyFooBar;
typedef ListWidget* MyFooBarPtr;
typedef std::vector< MyFooBarPtr > MyFooBarVec;
typedef MyFooBarVec* MyFooBarVecPtr;
Let's consider what the compiler does behind the scenes: We have two modules or translation units: Module A and B.
During compilation we would have the following:
Module A: namespace::class_name == foo::bar
Module B: namespace::class_name == foo::bar
During compilation of source code into object files these will compile fine separately as you have stated. The issue here isn't with the compiler.
The problem arises when it takes all of the object code or translation units and tries to link everything together to build a single executable.
This is when you end up having naming or symbol resolution conflicts which does violate the one definition rule. It is within the linker that problems arise.
However some compilers that are built within an integrated development environment such as Visual Studio may have some compiler flags that will "look ahead" so to speak to see if any possible conflicts may occur before compilation is done and this can generate compile time warnings or even errors before you even make it to the linker.
I would suggest either changing the class's name or the namespace name, however it would be more convenient to keep the namespace name over the class's name since that is the name space that represents your code base.
If for some reason you need to keep the class as the same name, then their may be one other alternative and that is to include a middle internal nested namespace name to resolve this conflict of naming to reduce ambiguity.
For example:
Module A: namespace::namespace::class_name = foo::ver_1::bar
Module B: namespace::namespace::class_name = foo::ver_2::bar
Then the interior nested namespace would prevent this naming conflict as long as you are not using directives such as:
#using namespace foo::ver_1;
#using namespace foo::ver_2;
Within the same visible scope!
There is one definition rule in C++ that you cannot have classes/functions defined twice. Not to mention the case when definitions are different.
That's being said, there are also isolation rules that allows you to bypass the one definition rule. Say, you have two classes with same name but they are defined and used only in two different .cpp files then everything should work...
Update: it might compile but it will do so because linker does a poor job of it. It won't work properly if definitions don't match. But it does work when you have project level separation, i.e., in different shared library files aka .dll - dynamic library level separation required, .cpp or static libraries separation level is not sufficient. Thx to #fdan and #FrancisCugler.
Basically, as long as there any projects that use both definitions somehow - lest there is a strong compilation boundary - it is a violation of one definition rule and cannot properly compile.
P.S. why even have two classes with identical name? This is an excellent source of bugs. If you want to have portable code between different architectures or OS systems, you can use #ifdef to remove the non-suitable version of the class from build.
First of all, thanks for your help. The issue seems to be with the QNX Momentics IDE itself. If I build the projects from the command line no warnings are printed. If I build the first MyFooBar from nested1 then one project from nested2 then the second MyFooBar from nested2 I am given this warning. If I build the first MyFooBar then several other projects from nested1 then the second MyFooBar, there are no such warnings. In either cases, the build is fine and everything works as expected.
Best Regards,
Ahmed
Is there any standard way to force users to use my dll library exactly in the same version used during compilation ?
Lets assume I have library in version 1.0 with a function:
extern "C" void A();
In version 1.1 I have added breaking change e.g.: another parameter to this function so I have:
extern "C" void A(int);
The exported name in dll is exactly the same but if the developer compile the product with version 1.1, then send it to the customer and the customer will update only the product (exe file) then everything will fail. And it may fail in random point at runtime (depending on when this changed function is executed).
Are there any standard ways to prevent loading the library in wrong version ? I'm mostly interested with solution for Windows dll files. (But if there are solutions specific to other platforms, please leave the comment)
The example above is simplified. Adding c++ mangling solves the particular problem above, but I'm looking for more general solution.
My idea is to add a static object in the library header file. This static object in constructor could execute method from the library and the method in name has encoded current version like: init_library_1_1(); So if the method is missing in dll then at very beginning user see that something is wrong. But the solution looks like a dirty workaround. And I have to take care that developer include this file.
Is there any better solution for such problem ?
There is no standard answer but many compiler/linker pairs have non-standard features to perform these kinds of tests.
Visual C++ for example has "#pragma detect_mismatch" that places a record in the output object file and then when the link is performed the records are tested and if they don't match an error is reported. I don't believe this would do any good if the DLL were loaded dynamically at run-time rather than statically during the load. I believe gcc/clang have something similar but don't know the details.
The best solution I was able to do:
In your .dll file add exported function:
extern "C"
{
DLL_FUNCTION void library_dll_required_in_version_10_0_1() {}
}
In public header add:
namespace library_impl{
extern "C"{
DLL_FUNCTION void library_dll_required_in_version_10_0_1();
}
class VersionProtection{
public:
VersionProtection() {
library_dll_required_in_version_10_0_1();
}
};
static VersionProtection aversion_protection_verifier;
}
Finally If user try to use application with wrong version of the dll file then he receive nice error message at program startup:
The procedure entry point library_dll_required_in_version_10_0_1
could not be located in the dynamic link library
You need to update the function version number after each breaking change.
I have a managed C++/CLI project which must use some native code. A simplified version of the native header file would be:
struct structA
{
// Some variables...
};
struct structB
{
// Some similar variables...
void convertTo(structA& dest);
};
This header is included in the managed code. The managed code has:
structA sA;
structB sB;
// Load data into sB...
sB.convertTo(sA);
I am using Visual Studio 2008 and compiling the managed code with /clr. This of course generates a linker error (LNK2028), as the implicit calling conventions differ. However I have been unable to use extern "C" declarations to solve this (or perhaps I'm using them wrong). I have tried several of the solutions provided to similar questions here, to no avail.
How do I correctly call the unmanaged function from the managed code? What declaration or wrapper is required here?
Turns out this was not a managed-unmanaged clash issue. I simply forgot to declare the used function as exported, i.e.,
__declspec(dllexport) void convertTo(structA& dest);
The second, more general linker error (LNK2019) for an unreferenced function was what I should have been paying attention to. It is strange that a managed-unmanaged clash error (LNK2028) was thrown as well, since this is a more specialized error (which also threw me off track). As far as I know, this error should only have applied was I to use /clr:pure, as was suggested in the comments as well.
This question already has answers here:
What is an undefined reference/unresolved external symbol error and how do I fix it?
(39 answers)
Closed 9 years ago.
I'm trying to wrap my head around C++ developement using the SFML library. I'm following a tutorial (http://www.gamefromscratch.com/page/Game-From-Scratch-CPP-Edition-Part-7.aspx), and using visual studio 2010.
A problem I keep running into regards unresolved externals. I'm really struggling with this, because unlike most errors I run into, it doesn't seem to a) have anything to do with the code, and b) doesn't behave consistently. Rather than give y'all a specific example and ask for help solving that one example, I'm hoping to develop a more reliable way of attacking these problems. I'll give you an outline of a common occurance though.
I have a solution with 8 header files and 8 cpp files that correspond to them. The solution is stable: It compiles and runs with no errors or warnings.
I'll go into a header file and add this line:
virtual void DoNothing();
I'll then go into the matching cpp file and write the method:
void DoNothing(){};
I compile and run, and get 5 unresolved external errors. They don't point to any line of code, so I don't really know how to fix them, but I obviously did something wrong. Fair enough. Trying to get back to a stable state, I delete the two lines of code I had inserted, and compile. Even though the code is identical to the last stable state, I get the same unresolved external errors.
Trying random things, I go into another cpp file and reverse the order of two included header files. The game compiles now. If I switch the order of the included header files back, it compiles.
What the hell are unresolved external errors? Why don't they seem to behave consistently with the code I've entered? How do I read them to find out what the problem is, and how do I avoid them in the first place?
Thank you.
ps: If there are more specific details I should provide, please just let me know.
"Unresolved External" errors mean that your code is referring to something (usually a function or method, but can be a variable too) that does not exist. These are link errors, and not compile errors; that's why you don't get a line number and more helpful error messages.
Let me give you a little background on how C++ code is turned into an executable (and keep in mind that I'm simplifying things a bit.)
Each C++ source file (and not header file) in your project is compiled separately. A ".cpp" file and all the headers it includes are compiled into what is called an object file or object code. (These files have a ".obj" or ".o" extension.) You can also think of library files (that is ".lib" files on Windows and ".a" files on Linux) as a collection of these object files, stored for later use.
To produce the executable programs (e.g. the EXE or DLL file on Windows) all these object files are linked together are voila!
Now, the important thing here is that each source file is compiled in isolation and independent from other source files. So, if the code in one file calls a function that is implemented in another file, the compiler won't see the actual body of that function and can only assume that as long as the declaration of the called function is visible (i.e. the prototype, i.e. the line you write in headers,) then these files are going to be linked together eventually and will leave the task of actually making the call to the linker. This usually means that as long as you include the right headers, your compiler is going to be happy.
But the linker is going to be more tenacious and pedantic. At link time, you really really need to provide the body (i.e. the implementation) of all the functions that you use all over the project. It is your task to make sure that all the right object files and libraries are linked together and the implementation of each used function exists somewhere among them exactly once (no more, no less.)
This brings us to your problem. When you get an "unresolved external" linker error, this means that the body of a function you've called does not exist anywhere in object files and libraries that you are linking together.
Obviously, one of two things is happening. Either you have included the header for an external library, but have forgotten to link in the library file itself (which is not your problem here) or you've declared (i.e. written the prototype for) a function but have forgotten to implement its body.
Keep in mind that the linker is really strict here. If you declare something like this in your class:
class Foo {
void bar (int x);
};
and then in your ".cpp" file, implement this function:
void bar (int x)
{
// Do nothing
}
then you'll get an unresolved external error if you actually call Foo::bar() anywhere in your program, because the implemented bar() is not a method of Foo (you should have implemented void Foo::bar (int x) {}.) Similar things happen if you slightly misspell or get the type of the arguments wrong or whatnot.
Reading linker errors and making sense from them can be hard. Sometimes, the name that the linker is complaining about (the "symbol" it says it can't find) is all mangled beyond recognition. This has to do with *Application Binary Interface*s (ABI) and several decades of history and precedence. Anyways, most of the time, if you look closely and the link error message, you can see what the function name was and check your code (or libraries) and try again.
Also, though it's rare, it sometimes happens that in order to solve some link issues, you have to resort to completely rebuilding your project.
Every time I've seen behavior like this it has been because of a circular reference between projects. For example, project A has a reference to an object/symbol implemented in project B while at the same time project B has a reference to an object/symbol from project A. Every time you build your solution, the tools have to compile one project first, then the other. If you make a change to the second project to be compiled, the first one cannot see the change on the first round of compilations and the build fails. If you manage to manually build project B (against a now obsolete copy of library B), then the solution starts to build correctly. More complex cycles are possible (e.g. A depends on B, which depends on C, which depends on A). You don't mention multiple projects explicitly, but I bet you have them.
These circular references are common on large solutions that have been around for a long time and have grown slowly over time. People get in habit of adding links from everything to everything because they need one function from here, a struct from there...
Hunt down these dependencies. You should be able to do a full clean rebuild from nothing but the source code. Your dependency tree should look like... Well, a tree; not a graph.
I've read the similar questions, but the one that answers mine applies only to VisualStudio. I am using Eclipse and developing an Android application using Cocos2d-X, which is a framework that uses Android's NDK. I created a class named Config, which contains all of the application's constants such as ball sizes and fps. Below is how I arranged the code.
Config.h
#ifndef __CONFIG_H_ // this was auto-generated by eclipse
#define __CONFIG_H_
class Config {
public:
static const double GRAVITY;
static const int BALL_WIDTH;
static const int BALL_HEIGHT;
}
#endif /* config.h */
Config.cpp
#include "Config.h"
const double Config::GRAVITY = 9.8;
const int Config::BALL_WIDTH = 100;
const int Config::BALL_HEIGHT = 100;
It compiles without errors, but when it begins linking, I get the following error:
multiple definition of `Config::GRAVITY'
C:/workspace/cocos2d-x/SampleGame/android/obj/local/armeabi/objs-debug/game/../../../Classes/Config.o:(.rodata+0xc8): first defined here
C:/workspace/cocos2d-x/SampleGame/android/obj/local/armeabi/objs-debug/game/../../../Classes/Ball.o:(.rodata+0xcc):`
The previous error occurs for all the constants declared. I have not included Config.cpp in the source code of any of the reported source files.
I have no idea how to correct this. I found an extremely similar question, but the answer was specified towards Microsoft's VisualStudio. Also, I'm sorry for using the 'cocos2d' tag, even if this applies to cocos2d-X, but I'm hoping someone knows how to fix this.
The only way that error could occur is if you're including the .cpp file around. Else, your code is perfectly Standards-compliant. After all, the error implies that the constant was defined in Ball.o, which I find very unlikely unless you included the cpp.
In your case, the names doesn't match. You are declaring as gravity and in cpp it's GRAVITY.
Edit: After your edit, I see no linking errors in your code unless you have defined GRAVITY in your Ball.cpp/h file also.