c++lnk2005

Error LNK2005 in C++ and ifndef don't work


I have a problem with Visual Studio 2012 & 2015 about the fact than it's seem than the "ifndef" don't work. I use the "ifndef" for "NAN" and "ifndef" for the header file and it's said these 2 errors (see the image). When I add the link "#include"Outil.h"" in the header of other file, I see the same message of error.

I always do like this before and it's always work. I don’t understand why it's doesn't work now even with only two files.

I also try to change the name of the first function "realoc_ungraded" but it's doesn't work and I get the same error.

Message of error

The message:

1) Warning: C4005: 'NAN': macro redefinition of math.h

2) Error: LNK2005: "struct tab_dynamo __cdecl realoc_ugraded(struct tab_dynamo,unsigned int)" (?realoc_ugraded@@YA?AUtab_dynamo@@U1@I@Z) already defined in main.obj Project1

3) Error: LNK1169: one or more multiply defined symbols found Projet

There is the code of the different file:

File main.cpp

#include"Outil.h"

int main(void) {

    return 0;
}

File Outil.h

#ifndef LIBRARY_OF_TOOLS
#define LIBRARY_OF_TOOLS 0

#define _USE_MATH_DEFINES

//NAN not defined in Visual Studio 2012, so I use the def. of VS 2015
#ifndef NAN
#define NAN ((float)(std::numeric_limits<float>::infinity*0.0F))
#endif

#include<iostream>
#include<string>
using namespace std;

#include<cmath>
#include<stdlib.h>
#include<stdio.h>
#include<assert.h>

#define ERROR_ADRESSE   0xcccccccc //default when not initialised
#define DEFAULT_LENGHT_TAB  1

//-----------------------------------------

typedef double type_data; //the type for calculation

//-----------------------------------------

/*Struct for my array*/
typedef struct {
    type_data *tab;
    unsigned int length;
}tab_dynamo;

//-----------------------------------------

template<typename T>
bool verify_ptr(const T *ptr) {
    return (ptr == NULL || ptr == (T*)(ERROR_ADRESSE));
}

//-----------------------------------------

template<typename T>
void see_tab(const T *tab, const unsigned int taille) {
    unsigned int i;
    cout << endl << endl;
    if (verify_ptr(tab) == false && taille > 0) {
        cout << endl;
        for (i = 0; i<taille; ++i) {
            cout << tab[i] << "\t";
        }
    }
    cout << endl << endl;
}

//-----------------------------------------

template<typename T>
T* realoc_ungraded(const T* original_tab, unsigned int *length, const unsigned int new_length) {
    T* new_tab = NULL;
    unsigned int precedent_length = 0, i;

    /*1) Exception case to directly exit*/
    if (new_length == 0) {
        return NULL;
    }

    /*2) Verification of the ptr of the length*/
    if (verify_ptr(length)) {
        length = (unsigned int*)calloc(1, sizeof(unsigned int));
        assert(length);
    }

    precedent_length = *length;
    *length = new_length;

    /*4) Creation of the new tab.*/
    new_tab = (T*)calloc(*length, sizeof(T));
    assert(new_tab);

    /*5) To transfert data of the original tab to the new tab*/
    if (precedent_length != 0 && verify_ptr(original_tab) == false) {
        for (i = 0; i < precedent_length && i < new_length; ++i) {
            new_tab[i] = original_tab[i];
        }
    }
    return new_tab;
}

//-----------------------------------------

//Version with the use of the struct "tab_dynamo"
tab_dynamo realoc_ungraded(tab_dynamo original_tab, const unsigned int new_length) {
    tab_dynamo tableau = { NULL, 0 };
    tableau.tab = realoc_ugraded(original_tab.tab, &original_tab.length, new_length);
    tableau.length = new_length;
    return tableau;
}



#endif

File Outil.cpp:

#include"Outil.h"

Solution

  • #ifndef NAN
    #define NAN ((float)(std::numeric_limits<float>::infinity*0.0F))
    #endif
    

    When preprocessor process these, the NAN is defined because it's not defined yet.

    #include<cmath>
    

    Then cmath maybe include math.h, and found NAN is defined by yours.

    You can try to change the sequence of include and your definition.

    #include <cmath>
    
    #ifndef NAN
    #define NAN ((float)(std::numeric_limits<float>::infinity*0.0F))
    #endif
    

    B.T.W If you compile using gcc, you could use -E option to see the output of preprocessor and know how the preprocess expand the macros.