Games with Out Linker Errors

Started by
9 comments, last by SpreeTree 19 years, 7 months ago
Greetings I started my game and am ALREADY GETTING BLOODY LINKER ERRORS!! Are there any tricks to making games that aren't going to give you linker errors? Menu.obj : error LNK2005: "unsigned int Game::GameState" (?GameState@Game@@3IA) already defined in Main.obj Menu.obj : error LNK2005: "struct tagRECT Menu::ExitBtn" (?ExitBtn@Menu@@3UtagRECT@@A) already defined in Main.obj Menu.obj : error LNK2005: "struct tagRECT Menu::H2HBattleBtn" (?H2HBattleBtn@Menu@@3UtagRECT@@A) already defined in Main.obj Menu.obj : error LNK2005: "struct tagRECT Menu::NewBtn" (?NewBtn@Menu@@3UtagRECT@@A) already defined in Main.obj GAAH!!
--------------------C++ Home - Check it out!Lol... - Amazing video
Advertisement
Don't link libraries?
Looks like you aren't using inclusion guards...
If at first you don't succeed, redefine success.
Change your project to a Multi-Threaded DLL
gib.son
Are you using an IDE, like Visual Studio or something?

What libraries are you specifically linking to? (other than the default ones). This is probably in the IDE project settings if you use one.

Another thing, sometimes there are different versions of functions for different settings (like debug-multithreaded-dll vs release-singlethreaded). I know SDL requires your project to use specific settings, so if you compiled parts of your project with different settings you might have double-ups on your functions. Unlikely.

If you gave more info, like listed above, you _might_ get more useful help.



Oh yeah, you also get this error if you #include files with function bodies that aren't inline or template. Make sure all your function bodies are inside the "c" or "c++" files, and that these are never #included.
I'm using the basic Win32 API only, And I do use header guards. That error was because I forgot to extern the variables. I still constantly come across errors though where It says "blah undefined symbol". It's really annoying! Headerguards and pragma once dont do anything sometimes. I'm using like I said just Win32. I'm not linking to other libraries except maybe winmm.lib occasionaly, and thats still never the source of the errors. All my errors are something is undefined yet it compiles, but doesnt link.
--------------------C++ Home - Check it out!Lol... - Amazing video
Teh refresher course for C and C++ source code file organization.

Yes, I said "teh" outside the lounge. Deal with it.
Don't link libraries?
Looks like you aren't using inclusion guards...
Change your project to a Multi-Threaded DLL

Incorrect.

Darobat - Don't define variables in header files. Read the article linked by Zahlman.
"Debugging is twice as hard as writing the code in the first place. Therefore, if you write the code as cleverly as possible, you are, by definition, not smart enough to debug it." — Brian W. Kernighan
Quote:Original post by Darobat
I'm using the basic Win32 API only, And I do use header guards. That error was because I forgot to extern the variables. I still constantly come across errors though where It says "blah undefined symbol". It's really annoying! Headerguards and pragma once dont do anything sometimes. I'm using like I said just Win32. I'm not linking to other libraries except maybe winmm.lib occasionaly, and thats still never the source of the errors. All my errors are something is undefined yet it compiles, but doesnt link.


You just have to bite the bullet. A linker error is as critical as a compile error. If it can't find the function, how the hell can the linker build the complete exe?

Although, I found VC6 particularly bad at linking, like 'forgetting' to re-compile some files, or messing up function pointers, or getting multiple definitions. It's got shitty dependencies checking. either use 'extern' or 'static' in the variable definition in the header, however, it's a VERY BAD idea (especially 'static').

Everything is better with Metal.

Hello,

there has been a lot of questions in the past days about "strange" linker errors. VC6 linker works correctly (well, it seems there are some rare bugs which allow the creation of a badly linked exe, but these can be avoided if you "Rebuild all" on a regular basis).

It seems that the concept of the link pass is not understood - I may understand this, since I never saw any information about the linker in programming books. The preprocessor pass is also a bit misunderstood by a lot of programmers - again, lack of information - but it is outside the scope of the problem.

There are 2 types of common linker error: the linker can complain about multiple definition of the same symbol or about a missing symbol definition. Since it is the linker which yells, you may think that this is not a compilation error. You are wrong. They are errors that the compiler cannot catch - this is a bit different.

1) multiple definitions
This one is (rather) simple. More than 2 different source file are defining the same symbol (sounds obvious). The original source of the problem may be different.
a) perhaps you add the symbol twice - cut-n-paste error anyone ?
b) perhaps the symbol definition is located inside a header file.
I put an emphasis on the word definition, because this is the most common source of error. The definition of a symbol is not the declaration of this symbol. The declaration tells the compiler that the symbol exists and thus allows the use of a particular symbol which is not yet defined. The latest sentence implies that a definition also acts like an implicit declaration. The definition implements the symbol as either a code piece or a memory chunk (depending on the symbol type : variable or function/method). Definitions and declarations do not use the same code syntax. A function declaration is followed by a semi-colon, like in the following statement:
int myFunction(int myParam);

A function definition defines the function code:
int myFunction(int myParam){  return 0;}

If you include the function definition in a header file and if you include the header file in more than one source code file, then you'll create multiple definitions of the myFunction function because the code of the function will be compiled more than once.
The same appies for variable definitions. This is a variable definition:
int myVariable;

If you add this code into more than one cpp file you'll get a linker error. You'll get an error too if you put this code in a header that is included in more than one cpp file. Now, you may have a problem because you want to use this variable in another cpp file - therefore, you need the variable declaration. The difference between a function declaration and a function definition is obvious. The difference between a variable declaration and a variable definition is - well, believe it or not - not so obvious :)
The only way to declare a variable which is defined in another cpp file is to specify that this symbol is external to the current cpp file. Hence the extern keyword:
extern int myVariable;


2) undefined symbol
This one is rather simple too, once you understand the difference bewteen a declaration and a definition. the "undefined symbol" linker error is generated when you use a declared symbol which is not defined.

A common source of this error comes from class static variables. This is because class variables seems to be defined once they are declared in the class declaration. This is not true. A class declaration just tells the compiler what is the internal of a class. It is harder to see because the class variable definition is implicit - the definition of a class instance also defines its members. This sould be simple. BUT (yes, of course, there's a BUT) this cannot be true for class static variables because of the meaning of this 'static' word in this particular context: "only one instance of the variable whatever the number of instance of the owner class". Therefore, this particular variable cannot be implicitely defined - because the static variable is not in the class, it is shared among all the insatnce of the class. As a conclusion, it has to be defined somewhere.

Another common error deals with missing libraries. I won't speak about this one - it is obvious, and the resolution do not depends on the code you wrote. Just change your linker settings accordingly.

Again another common error: name mangling can fool your linker. This is not the linker's fault, this is still yours :)

The name mangling problem arise when you want to use C declarations in a C++ project. The C++ compiler will generate decorated symbols (such as ?ToHex@@YA_NPDBAAK@)) but the C compiler you used before named the symbol as ToHex. There is a simple correction for this problem: declare your exported symbol as 'extern "C"':
extern "C" int myFunction(int myParam);

If you have more than one function to encapsulate then you may want to use the following:
#ifdef __cplusplusextern "C" {#endif// your declarations#ifdef __cplusplus}#endif


The __cplusplus preprocessor variable is defined by the C++ preprocessor if the compilation language is C++.

I may have forgotten some small things here, and I omit some others for the sake of clarity (static functions and so on).

HTH,

This topic is closed to new replies.

Advertisement