C++ link error, symbol redefinition - visual-c++

I came across a problem recently.
I have three files, A.h, B.cpp, C.cpp:
A.h
#ifndef __A_H__
#define __A_H__
int M()
{
return 1;
}
#endif // __A_H__
B.cpp
#include "A.h"
C.cpp
#include "A.h"
As I comile the three files by MSVC, there is a error:
C.obj : error LNK2005: "int __cdecl M(void)" (?M##YAHXZ) already defined in B.obj
It is easy understanding, as we know, B.obj has a symbol named "M", also C.obj has a "M".
Here the error comes.
However, if I change M method to a class which contain a method M like this below:
A.h
#ifndef __A_H__
#define __A_H__
class CA
{
public:
int M()
{
return 1;
}
};
#endif // __A_H__
there is no more errors!! Could somebody tell me what is happening?

If B.cpp and C.cpp include A.h, then both are compiled with your definition of M, so both object files will contain code for M. When the linker gathers all the functions, he sees that M is defined in two object files and does not know which one to use. Thus the linker raises an LNK2005.
If you put your function M into a class declaration, then the compiler marks/handles M as an inline function. This information is written into the object file. The linker sees that both object files contain a definition for an inline version of CA::M, so he assumes that both are equal and picks up randomly one of the two definitions.
If you had written
class CA {
public:
int M();
};
int CA::M()
{
return 1;
}
this would have caused the same problems (LNK2005) as your initial version, because then CA::M would not have been inline any more.
So as you might guess by now, there are two solutions for you. If you want M to be inlined, then change your code to
__inline int M()
{
return 1;
}
If you don't care about inlining, then please do it the standard way and put the function declaration into the header file:
extern int M();
And put the function definition into a cpp file (for A.h this would ideally be A.cpp):
int M()
{
return 1;
}
Please note that the extern is not really necessary in the header file.
Another user suggested that you write
static int M()
{
return 1;
}
I'd not recommend this. This would mean that the compiler puts M into both of your object files and marks M as being a function that is only visible in each object file itself. If the linker sees that a function in B.cpp calls M, it finds M in B.obj and in C.obj. Both have M marked as static, so the linker ignores M in C.obj and picks the M from B.obj. Vice versa if a function in C.cpp calls M, the linker picks the M from C.obj. You will end up with multiple definitions of M, all with the same implementation. This is a waste of space.

See http://faculty.cs.niu.edu/~mcmahon/CS241/c241man/node90.html how to do ifdef guards. You have to start with ifndef before the define.
Edit: Ah no, while your guard is wrong that's not the issue. Put static in front of your function to make it work. Classes are different because they define types.

I don't know what's under the hood, but if you don't need a class I guess that the compiler will automatically add the "extern" key to your functions, so you'll get the error including the header 2 times.
You can add the static keyword to M() method so you'll have only one copy of that function in memory and no errors at compile time.
By the way: I see you have a #endif, but not a #ifdef or #ifndef, is it a copy/paste error?

Related

create threaded class functions with arguments inside class

I have an object of class AI, which has a private non static void function which has a lot of arguments: minmax(double& val,double alpha, double beta, unsigned short depth, board* thisTurn); because this is a very time intensive function I want to use a number of threads to run it concurrently, therefor I must create a thread with this function inside another function inside the AI class;
According toThis question to make threads inside member functions containing non static member functions wiht no arguments of said class, one must call:
std::thread t(&myclass::myfunc,this);
And according to this tutorial threads of fucntions with multiple arguments can be created as such:
std::thread t(foo,4,5)
where the function 'foo' has 2 integer arguments
However I desire to mix these to things, to call a function which has arguments, which is also a non static member function, from inside the class that it is a member of, and i am not sure how to mix these to things.
I have off course tried (remember that it is inside a function inside the AI class):
std::thread t(&AI::minmax,val,alpha,beta,depth,thisTurn,this);
and
std::thread t(&AI::minmax,this,val,alpha,beta,depth,thisTurn);
But both cases fails with a compile error like this:
error: no matching constructor for initialization of 'std::thread'
candidate constructor template not viable: requires single argument '__f', but
7 arguments were provided
My question is therefor, if or if not, it is even possiple to -- from inside a member function of a class -- call a non static member function which has several arguments as a thread, and if this is the case, how it is done.
This question is however not wether or not it is a good idea to use multithreading in my specific case.
Edit
After doing some testing i realized that i can not call functions with arguments as threads at all, not even non-member functions with only one argument called directly from main, this was however solved by asking this other question where i realized that i simply need to add the flag -std=c++11 (because apparantly macs don't always use all c++11 features as standard) after doing so the answer works fine.
You need to wrap references using std::ref. The following example compiles fine:
#include <iostream>
#include <thread>
class board;
class AI
{
public:
void minmax(double& val, double alpha, double beta, unsigned short depth, board* thisTurn)
{
std::cout << "minmax" << std::endl;
}
void spawnThread()
{
double val;
double alpha;
double beta;
unsigned short depth;
board* thisTurn;
std::thread t(&AI::minmax, this, std::ref(val), alpha, beta, depth, thisTurn);
t.join();
}
};
int main()
{
AI ai;
ai.spawnThread();
}

I am not able to link 2 .cpp files with a header in visual studio

I have a file p2.cpp and 2d.cpp which I'm trying to link with 2d.h.
I have included 2d.h in both .cpp files and I'm getting an error:
2d.obj : error LNK2005: "float (* v)[3]" (?v##3PAY02MA) already defined in p2.obj
1: fatal error LNK1169: one or more multiply defined symbols found.
What should I do?
I have a file p2.cpp and 2d.cpp which I'm trying to link with 2d.h. I
have included 2d.h in both .cpp files and I'm getting an error:
Each symbol may only be defined in a program once (refer One definition rule). I'm not sure what you're header file looks like, but typically this means something to the effect of defining something in you're header file that is included in more than one compilation unit. You could "extern" it in you're header, and ensure that it is defined in a separate compilation unite.
From the compiler error it looks like you've define an array of pointers to functions in your header file. Extern this and provide a single definition in a source file.
This code effectively causes the problem:
//--- Def.h
#ifndef DEF_H
#define DEF_H
float foo();
/*extern */float (*floatFunctionArray[3])();
#endif /* DEF_H */
//--- Def.cpp
#include "Def.h"
float foo()
{
return 0;
}
float (*floatFunctionArray[3])() =
{
foo, foo, foo
};
//--- main.cpp
#include "Def.h"
int
main(int argc, char** argv)
{
return 0;
}
Adding the commented out "extern" solves the issue.

redefinition of default parameter error without redefining

I am getting a strange set of error in my Visual Studio 2010 compiler.
I am getting the errors of
error C2572: redefinition of default parameter
error C2011: 'class' type redefinition
I have checked thoroughly and I know very well that in the function definition, I have not given the default parameter values and I have given default parameter value only in function prototype in the header file.
Also, I am very much sure that no two class has been given the same class name.
Please can anybody tell me what could be the other reasons for getting these set of errors?
I have not got the exact reason why it was happening, but I have overcome it by using some simple techniques.
I used function overloading concept to avoid default parameter list. It will cause in duplication of code, but it has proved to be very effective.
So something like this
void myFunction( int, char * = '\0', char * = '\0' );
would become something like this
void myFunction( int );
void myFunction( int, char * );
void myFunction( int, char *, char * );
In this example, code is getting duplicated two times but it seems to be only work around solution.
Next, for the strange class type redefinition error, I was instantiating the class variable in many files. So, I removed that feature of instantiation everywhere and went with global variable something like this.
File named as myHeader.h
#include "myFile.h"
myClass myObj;
And in all the other files
#include "myHeader.h"
myObj.function1( );
myObj.function2( );

trouble with .inl files c++

i have a trouble with a function template implementation in a .inl file (visual c++)
I have this on a header file.
math.h ->>
#ifndef _MATH_H
#define _MATH_H
#include <math.h>
template<class REAL=float>
struct Math
{
// inside this structure , there are a lot of functions , for example this..
static REAL sin ( REAL __x );
static REAL abs ( REAL __x );
};
#include "implementation.inl" // include inl file
#endif
and this is the .inl file.
implementation.inl -->>
template<class REAL>
REAL Math<REAL>::sin (REAL __x)
{
return (REAL) sin ( (double) __x );
}
template<class REAL>
REAL Math<REAL>::abs(REAL __x)
{
if( __x < (REAL) 0 )
return - __x;
return __x;
}
the sine function throw me an error at run time when i call it. However , abs function works
correctly.
i think the trouble is the call to one of the functions of the header math.h inside the .inl files
why I canĀ“t use math.h functions inside .inl file ?
The problem has nothing to do with .inl files - you're simply calling Math<REAL>::sin() recursively until the stack overflows. In MSVC 10 I even get a nice warning pointing that out:
warning C4717: 'Math<double>::sin' : recursive on all control paths, function will cause runtime stack overflow
Try:
return (REAL) ::sin ( (double) __x ); // note the `::` operator
Also, as a side note: the macro name _MATH_H is reserved for use by the compiler implementation. In many cases of using an implementation-reserved identifier you'd be somewhat unlucky to actually run into a conflict (though you should still avoid such names). However, in this case that name has a rather high chance of conflicting with the one that math.h might actually be using to prevent itself from being included multiple times.
You should definitely choose a different name that's unlikely to conflict. See What are the rules about using an underscore in a C++ identifier? for the rules.

access array from struct in C

In my data.h file I have:
typedef struct {
double ***grid;
} Solver;
In my .c file I have
static Solver _solver;
which first makes a call to a function to do some allocation on grid such as
_solver.grid = malloc(....);
//then makes a call to
GS_init(_solver.grid);
The GS_init function is declared in GS.h as:
void GS_init(double ***grid);
When I try to compile, I get two errors:
the struct "<unnamed>" has no field "grid"
GS_init(_solver.grid)
^
and
too many arguments in function call
GS_init(_solver.grid)
^
Any ideas what is going wrong here?
This code compiles with 'gcc -Wall -Werror -c':
data.h
typedef struct
{
double ***grid;
} Solver;
gs.h
extern void GS_init(double ***grid);
gs.c
#include "data.h"
#include "gs.h"
#include <stdlib.h>
static Solver _solver;
void anonymous(void)
{
_solver.grid = malloc(32 * sizeof(double));
GS_init(_solver.grid);
}
Derek asked:
Why does this work? Is it because of the extern keyword?
The 'extern' is not material to making it work, though I always use it.
When I have to flesh out GS_init() in, say compute.c, would I write void GS_init(double ***grid){ //loop over grid[i][j][k] setting to zero }
Sort of...yes, the GS_init() code could do that if the data structure is set up properly, which is going to need more information than there is currently visible in the structure.
For the compiler to process:
grid[i][j][k] = 0.0;
the code has to know the valid ranges for each of i, j, and k; assume the number of rows in each dimension are Ni, Nj, Nk. The data 'structure' pointed to by grid must be an array of Ni 'double **' values - which must be allocated. Each of those entries must point to Nj 'double *' values. So, you have to do more allocation than a single malloc(), and you have to do more initialization than just setting everything to zero.
If you want to use a single array of doubles only, you will have to write a different expression to access the data:
grid[(i * Ni + j) * Nj + k] = 0.0;
And under this scenario, grid would be a simple double * and not a triple pointer.

Resources