Archived

This topic is now archived and is closed to further replies.

Sand_Hawk

VC 6 Linker trouble

Recommended Posts

I was working on a project off mine. I changed a variable into a HRESULT and tried to test the returned value. But when I compiled the project the linker start f*cking around. This is the output:
-------------------Configuration: Game - Win32 Debug--------------------
Compiling...
Game.cpp
DirectDraw.cpp
Linking...
DirectDraw.obj : error LNK2005: "public: __thiscall CDebug::CDebug(void)" (??0CDebug@@QAE@XZ) already defined in Game.obj
DirectDraw.obj : error LNK2005: "public: __thiscall CDebug::CDebug(char * const)" (??0CDebug@@QAE@QAD@Z) already defined in Game.obj
DirectDraw.obj : error LNK2005: "public: __thiscall CDebug::~CDebug(void)" (??1CDebug@@QAE@XZ) already defined in Game.obj
DirectDraw.obj : error LNK2005: "public: int __thiscall CDebug::SetFile(char * const)" (?SetFile@CDebug@@QAEHQAD@Z) already defined in Game.obj
DirectDraw.obj : error LNK2005: "public: int __thiscall CDebug::Write(char * const)" (?Write@CDebug@@QAEHQAD@Z) already defined in Game.obj
DirectDraw.obj : error LNK2005: "public: int __thiscall CDebug::Write(enum PRIORITY,char * const)" (?Write@CDebug@@QAEHW4PRIORITY@@QAD@Z) already defined in Game.obj
DirectDraw.obj : error LNK2005: "public: int __thiscall CDebug::Write(enum SORT,enum PRIORITY,char * const)" (?Write@CDebug@@QAEHW4SORT@@W4PRIORITY@@QAD@Z) already defined in Game.obj
Debug/Game.exe : fatal error LNK1169: one or more multiply defined symbols found
Error executing link.exe.

Game.exe - 8 error(s), 0 warning(s)
 
What''s going on? This is a header specificly and the header file contains it inclusion guards and has only 1 file(No CPP file). Sand Hawk ---------------- -Earth is 98% full. Please delete anybody you can.
My Site

Share this post


Link to post
Share on other sites
If by inclusion guards you are meaning the preprocessor directives such as #ifndef/#ifdef, realize that these only matter during COMPILE time. When you compile file A.cpp, which includes Debug.h -- the CDebug class gets declared and defined in your header. Compiler then moves on to compile B.cpp, which also includes Debug.h. CDebug is now in A.obj and B.obj. When the linker comes in, it notices A.obj and B.obj have definitions for CDebug, and this causes the error. The fix is to move the definition (implementation) of this class away from its declaration (interface). Debug.cpp would then be the only compiled program that has the definition of CDebug, and the linker would be happy.

Granted, your code would work as long as it was not included by more than one program in your project.

Hope this helps.

[edited by - SilentReaper on August 16, 2002 12:20:30 PM]

[edited by - SilentReaper on August 16, 2002 12:22:08 PM]

Share this post


Link to post
Share on other sites
I have currently only inside DirectDraw.H(own written file) Debug.H declared. Yesterday it compiled fine with the same setup. I didn''t change any includes since then(Actually, I commented out the including in my game.cpp). So, only defined inside DirectDraw.H

Sand Hawk

----------------
-Earth is 98% full. Please delete anybody you can.


My Site

Share this post


Link to post
Share on other sites
Yes, but do you #include "DirectDraw.h" from multiple .cpp files? If so, you are having the same problem I described with the preprocessor directives only being valid for that compiler instance. It''s just adding a layer between including it directly in your source files (assuming they are DirectDraw.cpp and Game.cpp now?)... Is that what''s happening or am I still not understanding?

Share this post


Link to post
Share on other sites
As a basic rule, functions belong in .cpp files, only type data and function prototypes belong in .h files.

This is different of course with inline functions and templates, but you get the general idea.

What you''re aiming for is for a function to only be compiled in one .cpp file but usable from anywhere.

I think there''s a tutorial on this (and other project structure issues) here on GameDev.


Helpful links:
How To Ask Questions The Smart Way | Google can help with your question | Search MSDN for help with standard C or Windows functions

Share this post


Link to post
Share on other sites
I see what you mean, I''m gonna put my class declaration inside the header and then I put all the functions inside the .cpp file.

Sand Hawk

----------------
-Earth is 98% full. Please delete anybody you can.


My Site

Share this post


Link to post
Share on other sites
Sand_Hawk: What does your Debug.h file look like? If it''s like this:

  
// Debug.h

#ifndef __DEBUG_H
#define __DEBUG_H

class CDebug {
public:
CDebug();
CDebug(char* const fileName);
~CDebug();

int SetFile(char* const fileName);
// Other functions declared

};

CDebug()
{
// Some default constructor stuff

}

CDebug(char* const fileName)
{
// Do some stuff with the supplied filename

}

~CDebug()
{
// Some destructor stuff

}

int CDebug::SetFile(char* const fileName)
{
// Do some stuff with the supplied filename

}
#endif // NOT __DEBUG_H


Then you will have the linker errors you''re seeing because the two constructors, the destructor, and all of your functions are being defined everytime this header is included (including, as SilentReaper says, everytime DirectDraw.h is included anywhere). Your options are to separate the function definitions (implementation) from the class declaration (interface) by using a separate Debug.cpp file, *or* if the functions are small enough, you can inline them all like this:

  
// Debug.h

// CDebug class with inline function definitions

#ifndef __DEBUG_H
#define __DEBUG_H
class CDebug {
public:
CDebug()
{
// Do some default constructor stuff

}
CDebug(char* const fileName)
{
// Do some stuff with the supplied filename

}
~CDebug()
{
// Some destructor stuff

}

int SetFile(char* const fileName)
{
// Do some stuff with the supplied filename

}
// ... other functions inlined the same way

};
#endif // NOT __DEBUG_H


The disadvantage of doing it this way is that any time you make a change to one of these inlined functions, every .cpp file that includes Debug.h directly or indirectly will need to be recompiled. If you separate the class into declaration (Debug.h) and definition (Debug.cpp) files, you can change the definition to your heart''s content without having to rebuild potentially your whole project.

HTH,

Cheers, dorix

Share this post


Link to post
Share on other sites