inline function redefinition linking error - c++

I got a class exported in dll. And got inline functions in that exported class:
Header.h
class MODULE_EXPORT A
{
public:
int GetInt(){ return iSomeInt; }
};
When I include that header file in a seperate module. I Got error LNK2005 which means: GetInt() already defined.
If I put the function definition in .cpp file . NO error occurs.
GetInt is inline function if I define it that way in the header file ,right? so why the redefinition linking error? I use the vc++ compiler. (Visual Studio 2010).
EDIT:
#pragma once
has already been added to the header file. Forgot to mention that.

Essentially for a function definition in a header file is visible to every compilation unit and they attempt to compile it.
However the function is already defined in the dll.
The solution would be place the definition in the cpp file as you noted or to use the static keyword so the definition is only visible to the compilation unit it's defined in and not ones that include it.
Also inlining functions is only a performance hint for the compiler, it may not inline it. And for this function I can't imagine their being any performance benefits given it's simplicity so I'd recommend moving it into the .cpp file.

Related

Multiple definitions of same function in C++

I am writing a library for neural nets. There are some necessary functions I needed so I separated them in a separate header file. I also provided the definition guards. I also included the header file in only one file but then also linker claims that there are multiple definitions of all the functions in the program.
The library structure is as follows:
namespace maya:
class neuron [neuron.hpp, neuron.cpp]
class ffnet [ffnet.hpp, ffnet.cpp]
struct connection [connection.hpp]
functions [functions.hpp]
the functions header file is written something like this:
#ifndef FUNCTIONS_HPP
#define FUNCTIONS_HPP
// some functions here
double random_double(){//some code}
#endif
this functions.hpp file is included only one in neuron.hpp and since ffnet is dependent on neuron, I included neuron.hpp in ffnet only once. This ffnet.hpp is included in main.cpp only once. main.cpp is file that I use for testing my library.
this linker throws error something like this:
/usr/bin/ld: /tmp/ccN7ywby.o: in function `maya::random_double()':
neuron.cpp:(.text+0x0): multiple definition of maya::random_double()'; /tmp/ccvDr1aG.o:main.cpp:(.text+0x0): first defined here
/usr/bin/ld: /tmp/cc66mBIr.o: in function `maya::random_double()':``
ffnet.cpp:(.text+0x0): multiple definition of `maya::random_double()'; /tmp/ccvDr1aG.o:main.cpp:(.text+0x0): first defined here
Also I compiled my program using :
g++ main.cpp neuron.cpp ffnet.cpp -o net
I don't think this will be needed but just in case :
$ uname -a
Linux brightprogrammer 4.19.0-kali3-amd64 #1 SMP Debian 4.19.20-1kali1 (2019-02-14) x86_64 GNU/Linux
You must write code of random_double() in .cpp file other than .hpp or .h file. Or, add inline before double random_double() { //some code } if you keep your code in your .hpp file.
The problem
You have your function definition with their full code in a header that you include in several compilation units. This causes the function to be defined in each compilation unit (cpp) and this breaks the One Definition Rule (ODR).
The include guards make sure that the same definition doesn't occur several time in the same compilation unit (e.g. if you include function.hpp in neuron.hpp and also include it directly). But here this header is included directly or indirectly in main.cpp, ffnet.cpp and neuron.cpp, which makes a first definition and 2 invalid redefinitions.
The solution
You must change function.hpp to keep only the function declaration:
#ifndef FUNCTIONS_HPP
#define FUNCTIONS_HPP
double random_double(); // no body !!
#endif
and move the function bodies to a separate function.cpp, which must be added to your compiler command.
The advantage of this approach are:
You can then compile the utility functions separately. Every time you'd change the function body, you'd no longer have to recompile all the cpp.
Encapsulation is improved, by sharing in the hpp only what other modules need to know, and hiding the implementation details.
Reuse could be facilitated across projects by making a library of functions.
The includes would be shorter (in case in some distant future your code would evolve to a large project with thousands of hpp, this could make you gain some time)
Additional remarks
Not sure that it applies, but be aware also that it's not a good idea to include a header into a namespace.
I also recommend reading this article about headers. It's old but the advice is still very relevant :-)
Note that there are exceptions to the ODR for classes and inline functions, in which case the multiple definitions must be exactly the same sequence of tokens.

One Definition Rule - compilation

I am trying to understand ODR.
I created one file pr1.cpp like this:
struct S{
int a;
};
a second file pr2.cpp like this
struct S {
char a;
};
and a main file like this :
#include <iostream>
int main() {
return 0;
}
I am compiling using terminal with the command :
g++ -Wall -Wextra pr1.cpp pr2.cpp main.cpp -o mypr
The compiler does not find any kind of error BUT there are two declarations of the type "S"...I am not understanding what is really happening..I thought to get an error after the "linkage" phase because of the ODR violation..
I can get the error only editing the main.cpp file adding :
#include "pr1.cpp"
#include "pr2.cpp"
Can anyone exmplain me what is happening?
Unless you include both definitions in the same file, there is no problem. This is because the compiler operates on a single translation unit which is usually a .cpp file. Everything you #include in this file is also part of the translation unit because the preprocessor basically copies and pastes the contents of all included files.
What happens is that the compiler will create and object file (.obj usually) for each translation unit and then the linker will create a single executable (or .dll etc) by linking all the object files and the libraries the project depends on. In your case the compiler encountered each struct in a different translation unit so it doesn't see a problem. When you include both files, the two definitions now find themselves in the same translation unit and the compiler throws an error because it cannot resolve the ambiguity if an S is used in this translation unit (even though you don't have to use one for the program to be ill-formed).
As a side-note, do not include .cpp files in other .cpp files. I'm sure you can find a lot on how to organize your code in header and source files and it doesn't directly answer the question so I won't expand on it.
EDIT: I neglected to say why you didn't get a linker error. Some comments have pointed out that this is undefined behavior which means that even though your linker should probably complain it doesn't actually have to. In your case you have one .obj file for each struct and a main.obj. None of these references the other so the linker does not see any references that it needs to resolve and it probably doesn't bother checking for ambiguous symbols.
I assume most linkers would throw an error if you declared struct S; and tried to use a S* or S& (an actual S would require definition inside the same translation unit). That is because the linker would need to resolve that symbol and it would find two matching definitions. Given that this is undefined, though, a standard-compliant linker could just pick one and silently link your program into something nonsensical because you meant to use the other. This can be especially dangerous for structs that get passed around from one .cpp to the other as the definition needs to be consistent. It might also be a problem when identically named structs/classes are passed through library boundaries. Always avoid duplicating names for these reasons.

Are header files not compiled (C++ Visual Studio 2015)

Just to see if it would work (I know it's awful form), I fully defined a function in a header file and made a corresponding forward declaration for said function in the main cpp file. C++ functions don't need to be defined in the translation unit they're used in, hence why header files are almost entirely just forward declarations (with the exception of inline functions). However, when I tried to compile this project, it said that there were unresolved externals.
When I moved the entire contents of the header file into a source file (removing the header file as well), it compiled just fine and executed as expected. So, are header files just not compiled when building a project, or is there just some exception I don't know about?
Additionally, even when I just go to the header file's properties in the property explorer and set its File Type to C/C++ Code and change its extension to .cpp, it still won't compile (even though it will if i just delete it and create a fresh source file, which I think is the oddest part).
(I'm working with extensions disabled /Za, if that changes anything)
Here's the code file
//main.cpp
void foo();
void main()
{
foo();
}
and the header file
//test.h
#include <iostream>
void foo()
{
std::cout << 'a';
}
Header files are included by the preprocessor into the compilation unit - cpp file. Only the source code in the cpp file is compiled by compiler after that.
When you put your function definition into the header .h file. You don't include this header file into main.cpp and compiler doesn't compile it as preprocessor doesn't include it in main.cpp.
You can review the result of preprocessor job by yourself. In Visual Studio use the /P option on the Preprocessor property page. For main.cpp output will be in main.i.
Header files are not compiled on their own, just imagine that the text is actually inside the .cpp file where it is included. This new 'merged' file is what is compiled. So you can put functions in a header file and it will be compiled when it is included in a .cpp file.
The reason it's bad is that if you include it in a second .cpp file it will try to compile again and you will have problems.
The problem with function definitions in headers is not that they're skipped. The real risk is that they're compiled twice, and that's once too many. C++ has something called a One Definition Rule, and you violate that rule by compiling a single function twice.
There's one important exception to mention: inline functions are exempt, and may be defined in each translation unit.

tracking down LNK2005: "already defined"

I have been working on a program in windows VC++ 2008. I started by having all of my code in .cpp files (just to get everything working), and now breaking things into .h, and .cpp files. when I compile I get a mountain of LNK2005 errors stating that:
Object.obj : error LNK2005: "__thiscall thing::thing(args)" already defined in otherObject.obj
while I was making the original program I kept getting errors of undeclared identifier, and so I gave a include directive to satisfy that. now when I am breaking everything up into separate .cpp, and .h files I get all of this. which place do I start looking (Object, otherObject, or thing), or somewhere else.
Basically you have definition for thing::thing(args) in two Translation Units(TU), which violates the One Definition Rule(ODR) and hence the error.
The linker exactly tells you which TU's are involved: otherObject.obj and Object.obj.
Start looking in to otherObject.cpp and Object.cpp and the headers which are included in these two cpp files. It is most likely that you have defined your constructor thing::thing(args) in header file and including that header file in both these cpp files results in multiple definitions.
Suggested Solution:
You cannot define the constructor in header file, You need to add it to your cpp file along with other member functions of the class. If you must add the definition of constructor to header you should mark it inline, given that You have not shown your code I don't see any reason to apply the second approach.
Given the information in your question, I bet that the method is defined in a header file but not marked inline. This then causes duplicate symbol linker errors. Try marking hte method inline or moving the definition to a source (.C) file.

One or more multiply defined symbols found

DebugUtil.h
#ifndef DEBUG_UTIL_H
#define DEBUG_UTIL_H
#include <windows.h>
int DebugMessage(const char* message)
{
const int MAX_CHARS = 1023;
static char s_buffer[MAX_CHARS+1];
return 0;
}
#endif
When I try to run this I get this error:
Terrain.obj : error LNK2005: "int
__cdecl DebugMessage(char const *)" (?DebugMessage##YAHPBD#Z) already
defined in Loodus.obj
Renderer.obj : error LNK2005: "int
__cdecl DebugMessage(char const *)" (?DebugMessage##YAHPBD#Z) already
defined in Loodus.obj
test.obj : error LNK2005: "int __cdecl
DebugMessage(char const *)"
(?DebugMessage##YAHPBD#Z) already
defined in Loodus.obj
C:\Users\Tiago\Desktop\Loodus
Engine\Debug\Loodus Engine.exe : fatal
error LNK1169: one or more multiply
defined symbols found
But why does this happen? I have #ifndef #define and #endif in the header so multiple definitions shouldn't happen
Put the definition (body) in a cpp file and leave only the declaration in a h file. Include guards operate only within one translation unit (aka source file), not across all your program.
The One Definition Rule of the C++ standard states that there shall appear exactly one definition of each non-inline function that is used in the program. So, another alternative would be to make your function inline.
Make the function inline or declare the function in a header file and define it in a cpp file.
inline int DebugMessage(const char* message)
{
const int MAX_CHARS = 1023;
static char s_buffer[MAX_CHARS+1];
return 0;
}
EDIT:
As a comment by Tomalak Geret'kal suggests, it's better to use my latter suggestions than my former and move the function's declaration to a cpp file.
(Assuming the posted code is a header, included from multiple .cpp files)
Header guards do not protect you from link-time multiple definitions. Regardless that you have ensured the header will only appear once per Translation Unit, if you have more than one Translation Unit then that's still multiple definitions.
Write definitions in source files, and only declarations in headers.
The only exceptions are inline functions, functions defined within a class definition (though this is not recommended!) and function templates.
This function is included into every translation unit and as a result you get multiple definitions of it - each .obj file contains its own copy. When it's time to link them all together the linker rightfully shows the above error.
You can do a few things:
Move the definition to a .cpp file and keep only the declaration in the header.
Use an anonymous namespace around the function in your header file (but realize it's a hack - you will still have multiple definitions, just no name collision).
Mark it as inline (although it might not always work - only if the compiler actually chooses to inline it). That's also a hack for the same reason as above.
That only prevents multiple inclusions in the same source file; multiple source files #includeing it will still generate multiple definitions of DebugMessage(). In general, you should either not place functions in header files at all or make them static (and usually inline, since otherwise it doesn't usually make sense to have multiple static definitions of the same function).
100% Certain you correctly included Guards but still getting redefinition error?
For Visual Studio:
I was really frustrated because I was correctly included guards,
only to find out the problem was visual studio. If you have added the file
to your project, the compiler will add the file twice even if you have
include guards around your implementation file and header file.
If you don't use visual studio exclusively, and say... use code::blocks sometimes, you might want to only #include the file when you detect the absence of the visual studio environment.
DebugUtil.h :
----------------------
#ifndef _WIN32
#include "DebugUtil.c"
#endif
----------------------
If you are okay with including stdio.h,
you can be a little less hackish about it:
DebugUtil.h :
----------------------
#include <stdio.h>
#ifdef _MSC_VER
#include "DebugUtil.c"
#endif
----------------------
Reference:
Predefined Macros, Visual Studio:
https://msdn.microsoft.com/en-us/library/b0084kay.aspx
Move the definition to a .cpp file.
Declare your functions in C++ files. Since you defined your function in the header file, and that header file is included from multiple source files, it gets defined for each source file that includes it. That's why it's reported as being defined in multiple places.
Alternatively, you could make it inline so that the code is inserted wherever it's used instead of being defined as a separate function each time.
It looks like you are including DebugUtil.h in more than one translation unit, then linking those objects together. However, DebugUtil.h provides a definition for the DebugMessage function, so that definition exists in all of the translation units that incorporated the header. As a result, when you link the objects, the linker rightly complains that the symbol is multiply defined.
Change DebugUtil.h so that it declares DebugMessage via a prototype, but does not provide a definition, and place the definition of DebugMessage in a .c file which you will compile and link with your other objects.