Function Redefinition Errors

Whether you're a newbie or an experienced programmer, any questions, help, or just talk of any language will be welcomed here.

Moderator: Coders of Rage

Post Reply
RandomDever
Chaos Rift Regular
Chaos Rift Regular
Posts: 198
Joined: Thu Mar 26, 2009 8:42 pm
Current Project: My Engine
Programming Language of Choice: C++

Function Redefinition Errors

Post by RandomDever »

So I'm building a new version of my engine from scratch for my next big project and I've been running into a problem lately.
Example:

Code: Select all

1>input.obj : error LNK2005: "bool Debug::debug" (?debug@Debug@@3_NA) already defined in program.obj
1>input.obj : error LNK2005: "class std::basic_ofstream<char,struct std::char_traits<char> > Debug::debugFile" (?debugFile@Debug@@3V?$basic_ofstream@DU?$char_traits@D@std@@@std@@A) already defined in program.obj
1>debug.obj : error LNK2005: "bool Debug::debug" (?debug@Debug@@3_NA) already defined in program.obj
1>debug.obj : error LNK2005: "class std::basic_ofstream<char,struct std::char_traits<char> > Debug::debugFile" (?debugFile@Debug@@3V?$basic_ofstream@DU?$char_traits@D@std@@@std@@A) already defined in program.obj
Is there any way to prevent this from happening?
It's probably some ridiculously obvious well known programming practice, but keep in mind I don't have a college education.
Any help is greatly appreciated. :)
Thank you.
User avatar
bbguimaraes
Chaos Rift Junior
Chaos Rift Junior
Posts: 294
Joined: Wed Apr 11, 2012 4:34 pm
Programming Language of Choice: c++
Location: Brazil
Contact:

Re: Function Redefinition Errors

Post by bbguimaraes »

My first guess is include guards are missing.
RandomDever
Chaos Rift Regular
Chaos Rift Regular
Posts: 198
Joined: Thu Mar 26, 2009 8:42 pm
Current Project: My Engine
Programming Language of Choice: C++

Re: Function Redefinition Errors

Post by RandomDever »

If you mean the #ifndef guards then no I remembered those ( which only serves to confuse me more ).

EDIT: If I knew how to make global variables that I can access from any file this problem could be resolved. Does anyone know how to do that?
Because right now I'm just using namespaces, which apparently don't work as I intend.
User avatar
bbguimaraes
Chaos Rift Junior
Chaos Rift Junior
Posts: 294
Joined: Wed Apr 11, 2012 4:34 pm
Programming Language of Choice: c++
Location: Brazil
Contact:

Re: Function Redefinition Errors

Post by bbguimaraes »

Code: Select all

// some_file.h
#ifndef SOME_FILE_H
#define SOME_FILE_H

namespace Debug {
    bool debug;
}

#endif // SOME_FILE_H

// other_file.cpp
#include <some_file.h>

void f() {
    Debug::debug = true;
}
Does that help?
RandomDever
Chaos Rift Regular
Chaos Rift Regular
Posts: 198
Joined: Thu Mar 26, 2009 8:42 pm
Current Project: My Engine
Programming Language of Choice: C++

Re: Function Redefinition Errors

Post by RandomDever »

Apparently, not. I tried it and I still got the linker errors. :(
RandomDever
Chaos Rift Regular
Chaos Rift Regular
Posts: 198
Joined: Thu Mar 26, 2009 8:42 pm
Current Project: My Engine
Programming Language of Choice: C++

Re: Function Redefinition Errors

Post by RandomDever »

I don't think I will ever understand how c++ works.
It works now... I have no idea why. It just does.
Well thanks for trying anyways...
User avatar
bbguimaraes
Chaos Rift Junior
Chaos Rift Junior
Posts: 294
Joined: Wed Apr 11, 2012 4:34 pm
Programming Language of Choice: c++
Location: Brazil
Contact:

Re: Function Redefinition Errors

Post by bbguimaraes »

"Already defined" errors occur when you declare a name (which can be a variable, class, function, etc) on more than one place. You need to declare the name once in a header file with include guards. Then, on other files where you use the name, you need only include the file, not declare it again.

Try reducing your code to the least necessary to reproduce the error. If you still can't solve it, post a sample and we will try to help.

And don't worry, c++ takes time to understand (and a lifetime to master).
User avatar
YourNerdyJoe
Chaos Rift Cool Newbie
Chaos Rift Cool Newbie
Posts: 79
Joined: Sun Oct 02, 2011 3:28 pm
Current Project: Top secret (not really) Top-Down Shooter for GBA
Favorite Gaming Platforms: GBA, Gamecube, PC, 3DS
Programming Language of Choice: C/C++
Contact:

Re: Function Redefinition Errors

Post by YourNerdyJoe »

change

Code: Select all

namespace Debug {
    bool debug;
}
to

Code: Select all

namespace Debug {
    static bool debug;
}
and it should work
See that?.....
Exactly
https://yournerdyjoe.github.io/
User avatar
Falco Girgis
Elysian Shadows Team
Elysian Shadows Team
Posts: 10294
Joined: Thu May 20, 2004 2:04 pm
Current Project: Elysian Shadows
Favorite Gaming Platforms: Dreamcast, SNES, NES
Programming Language of Choice: C/++
Location: Studio Vorbis, AL
Contact:

Re: Function Redefinition Errors

Post by Falco Girgis »

RandomDever wrote:It's probably some ridiculously obvious well known programming practice, but keep in mind I don't have a college education.
I take personal offense to this. Even though I HAVE a college education, I learned to code and develop on my own time. That's taking credit away from me teaching myself and giving credit to my college which didn't teach me shit. A degree means nothing about your programming efficacy. I know plenty of college grads who can't code for shit and highschool dropouts who are coding gurus. Don't let me catch you saying shit like that again. ;)

Considering the fact that you haven't bothered to post the offending header file, I take it we're all stabbing in the dark here? My turn.
bbguimaraes wrote:

Code: Select all

namespace Debug {
    bool debug;
}

#endif // SOME_FILE_H

// other_file.cpp
#include <some_file.h>

void f() {
    Debug::debug = true;
}
That is most DEFINITELY not going to work. That's probably what is causing the error anyway.

Every .cpp file including that header file now has a duplicate declaration of the debug boolean flag, hence the linker errors.
YourNerdyJoe wrote:change

Code: Select all

namespace Debug {
    bool debug;
}
to

Code: Select all

namespace Debug {
    static bool debug;
}
and it should work
If your definition of "work" is compile, link, and run, then yes, it will work.

If your definition of "work" is operate correctly, then no. What you have now done is given each .cpp its very own private (static) instance of the debug flag. This resolves the duplicate symbol, because every .cpp file now has its own debug flag, but if the intent of the global was to allow access to this flag throughout the program, you're still wrong.

One word: EXTERN

Change

Code: Select all

namespace Debug {
    bool debug;
}
to

Code: Select all

namespace Debug {
    extern bool debug;
}
within your header file.

Then put

Code: Select all

namespace Debug {
    bool debug;
}
into a .cpp file somewhere.

The first extern declaration tells each .cpp file including the header file that there exists a variable declared elsewhere called debug. You are NOT allocating that variable, you are simply telling the compiler that it is allocated elsewhere.

Then the second declaration in the .cpp file actually allocates the variable. When the linker links each file's extern declaration from the header file, they now all point back to the same variable allocated within the .cpp.
User avatar
bbguimaraes
Chaos Rift Junior
Chaos Rift Junior
Posts: 294
Joined: Wed Apr 11, 2012 4:34 pm
Programming Language of Choice: c++
Location: Brazil
Contact:

Re: Function Redefinition Errors

Post by bbguimaraes »

Yeah, that was my bad, I forgot about the extern. Your Debug::debugFile is going to need to be declared as external and be defined on a cpp file too. The definitions on the .cpp file can be made shorter:

Code: Select all

bool Debug::debug;
ofstream Debug::debugFile;
RandomDever wrote:EDIT: If I knew how to make global variables that I can access from any file this problem could be resolved. Does anyone know how to do that?
Because right now I'm just using namespaces, which apparently don't work as I intend.
Namespaces exist to avoid name collisions. Its purpose has nothing to do with what we are discussing here. To declare a global variable and use it in other files, you need to do it as Falco showed. But try to avoid using global variables, if you can. Or better said, try to avoid making code dependent on global variables (which usually leads to not using them at all).
User avatar
YourNerdyJoe
Chaos Rift Cool Newbie
Chaos Rift Cool Newbie
Posts: 79
Joined: Sun Oct 02, 2011 3:28 pm
Current Project: Top secret (not really) Top-Down Shooter for GBA
Favorite Gaming Platforms: GBA, Gamecube, PC, 3DS
Programming Language of Choice: C/C++
Contact:

Re: Function Redefinition Errors

Post by YourNerdyJoe »

Falco Girgis wrote:
YourNerdyJoe wrote:change

Code: Select all

namespace Debug {
    bool debug;
}
to

Code: Select all

namespace Debug {
    static bool debug;
}
and it should work
If your definition of "work" is compile, link, and run, then yes, it will work.

If your definition of "work" is operate correctly, then no. What you have now done is given each .cpp its very own private (static) instance of the debug flag. This resolves the duplicate symbol, because every .cpp file now has its own debug flag, but if the intent of the global was to allow access to this flag throughout the program, you're still wrong.

One word: EXTERN

Change

Code: Select all

namespace Debug {
    bool debug;
}
to

Code: Select all

namespace Debug {
    extern bool debug;
}
within your header file.

Then put

Code: Select all

namespace Debug {
    bool debug;
}
into a .cpp file somewhere.

The first extern declaration tells each .cpp file including the header file that there exists a variable declared elsewhere called debug. You are NOT allocating that variable, you are simply telling the compiler that it is allocated elsewhere.

Then the second declaration in the .cpp file actually allocates the variable. When the linker links each file's extern declaration from the header file, they now all point back to the same variable allocated within the .cpp.
Didn't realize that was the difference between static and extern. Thanks for the edjukation Falco ;)
See that?.....
Exactly
https://yournerdyjoe.github.io/
Post Reply