Multiple def. error during make

Hi while compiling I get multiple def. errors like this
1
2
3
SubVecProcessor.o: In function `chrtopch(char)':
SubVecProcessor.cpp:(.text+0x0): multiple definition of `chrtopch(char)'
subv.o:subv.cpp:(.text+0x0): first defined here

for all of my functions declared in functionlib.h

./include/functionlib.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
#ifndef FUNCTIONLIB_H
#define FUNCTIONLIB_H

#include <stdio.h>
#include <stdlib.h>
#include <stdexcept>
#include <ios>
#include <cmath>
#include <iostream>
#include <fstream>
#include <ostream>
#include <istream>
#include <vector>
#include <limits>
#include <sstream>
#include <dirent.h>
#include <string.h>

#include "nr3.h"

using namespace std;

template <class T> NRvector<T> convertVec(vector<T> inputVec){...}
char *strtopch(string str){...}
char *chrtopch(char chr){...}

string streamChar(char *pchstr, int increment, int character, string swap){...}
string streamChar(char chstr, int increment, int character, string swap){...}
#endif /*FUNCTIONLIB_H*/ 



./include/SubVecProcessor.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
#ifndef SUBVECPROCESSOR_H
#define SUBVECPROCESSOR_H

#include <stdio.h>
#include <stdlib.h>
#include <stdexcept>
#include <ios>
#include <cmath>
#include <iostream>
#include <fstream>
#include <ostream>
#include <istream>
#include <vector>
#include <limits>
#include <sstream>
#include <dirent.h>
#include <string.h>

#include "functionlib.h"

class SubVecProcessor{
        public:
                SubVecProcessor(NRvector<std::string> *_FileList, std::string _firstCandidate);
                ~SubVecProcessor();

                NRvector<std::string> get();
                NRvector<std::string> getNext();
                void renew();
                int getSize();

        private:
                NRvector<std::string> *FileList;
                NRvector<std::string> *subvec;
                NRvector<int> *countList;

                NRvector<std::string> *sortingList;
                NRvector<int> *numberList;
                std::string firstCandidate;

                void makeNumerberList();
                NRvector<std::string> *quickSort(int le, int ri);


                int SIZE;
                int CountListSize;
                int CountListEntry;

                void generate();
                void makeCountList();
                int findLast(int entryPoint);
                void nextSubVec();
                void makeSubVector(int entryPoint, bool jumper);
};

#endif /*SUBVECPROCESSOR_H*/ 


subv.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
#include <stdio.h>
#include <stdlib.h>
#include <stdexcept>
#include <ios>
#include <cmath>
#include <iostream>
#include <fstream>
#include <ostream>
#include <istream>
#include <vector>
#include <limits>
#include <sstream>
#include <dirent.h>
#include <string.h>

#include "./include/SubVecProcessor.h"

using namespace std;

NRvector<string> createFileList(char *workingDir, string fileType, const string expName){...}

int main(){

        int counts=0;
        char *workingDir="./data";
        string fileType="ini";
        string expName="Th";

        NRvector<std::string> FileList = createFileList(workingDir, fileType, expName);


        SubVecProcessor genA(&FileList, expName);

        return 0;
}



Makefile
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
CC=g++
CFLAGS=-O2 -Wall
LDFLAGS=-lm

all : subv

#SubVecGenerator.o : ./src/SubVecGenerator.cpp ./include/SubVecGenerator.h ./include/nr3.h
#       $(CC) $(CFLAGS) -c ./src/SubVecGenerator.cpp

SubVecProcessor.o : ./include/SubVecProcessor.h ./include/nr3.h ./include/functionlib.h ./src/SubVecProcessor.cpp
        $(CC) $(CFLAGS) -c ./src/SubVecProcessor.cpp

subv.o : ./include/SubVecProcessor.h subv.cpp
        $(CC) $(CFLAGS) -c subv.cpp

subv : subv.o SubVecProcessor.o
        $(CC) $(CFLAGS) subv.o SubVecProcessor.o $(LDFLAGS) -o subv
        rm -rf *o ./include/*.gch
        
clean:
        rm -rf *.o subv ./include/*.gch */



Fyi I built a program with a similar structure. And it complies fine without any errors.
I have to say, I'm a looser at Makefiles. :D
Thanks in advance =)


The problem is that chrtopch will be defined each time for each .cpp file that includes functionlib.h. This is not allowed for regular functions. The solution is to mark it as inline or define it inside a .cpp file and just declare it in the header file.
Last edited on
But I am only including it once @SubVecProcessor.
SubVecProcessor.h includes functionlib.h so all files that includes SubVecProcessor.h will also include the content of functionlib.h.
To me, it looks like you're including it once in SubVecProcessor.cpp and once in subv.cpp. The linker is therefore finding two definitions for each of those functions.

As Peter87 says, you should put the function definitions into a separate .cpp file, rather than including them in multiple .cpp files (via a header). You'll still need the function declarations in the heaser, but the definitions should go into a .cpp.
So now I have split functionlib.h ind to functionlib.h and functionlib.cpp.

And I've edited the Makefile to
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
CC=g++
CFLAGS=-O2 -Wall
LDFLAGS=-lm

all : subv

#SubVecGenerator.o : ./src/SubVecGenerator.cpp ./include/SubVecGenerator.h ./include/nr3.h
#       $(CC) $(CFLAGS) -c ./src/SubVecGenerator.cpp

functionlib.o : ./include/functionlib.h ./src/functionlib.cpp
        $(CC) $(CFLAGS) -c ./src/functionlib.cpp

SubVecProcessor.o : ./include/SubVecProcessor.h ./include/nr3.h ./include/functionlib.h ./src/SubVecProcessor.cpp
        $(CC) $(CFLAGS) -c ./src/SubVecProcessor.cpp

subv.o : ./include/SubVecProcessor.h ./include/nr3.h ./include/functionlib.h subv.cpp
        $(CC) $(CFLAGS) -c subv.cpp

subv : subv.o SubVecProcessor.o functionlib.o
        $(CC) $(CFLAGS) subv.o SubVecProcessor.o functionlib.o $(LDFLAGS) -o subv
        rm -rf *o ./include/*.gch
        
clean:
        rm -rf *.o subv ./include/*.gch
 */



I now get
1
2
3
4
5
6
7
8
9
10
11
g++ -O2 -Wall -c subv.cpp
subv.cpp: In function ‘int main()’:
subv.cpp:29: warning: deprecated conversion from string constant to ‘char*’
subv.cpp:28: warning: unused variable ‘counts’
g++ -O2 -Wall -c ./src/SubVecProcessor.cpp
g++ -O2 -Wall -c ./src/functionlib.cpp
g++ -O2 -Wall subv.o SubVecProcessor.o functionlib.o -lm -o subv
subv.o: In function `createFileList(char*, std::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::basic_string<char, std::char_traits<char>, std::allocator<char> >)':
subv.cpp:(.text+0x5c9): undefined reference to `NRvector<std::basic_string<char, std::char_traits<char>, std::allocator<char> > > convertVec<std::basic_string<char, std::char_traits<char>, std::allocator<char> > >(std::vector<std::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::allocator<std::basic_string<char, std::char_traits<char>, std::allocator<char> > > >)'
collect2: ld returned 1 exit status
make: *** [subv] Error 1
Have you changed subv.cpp at all from what you posted in your OP? The line numbers in the errors don't seem to match the code.

Anyway,

warning: deprecated conversion from string constant to ‘char*’

refers to the line:

char *workingDir="./data";

Why not simply use a std::string like you have for your other strings?

warning: unused variable ‘counts’

should be pretty self-explanatory.

The linker error is telling you that it can't find a definition of the template function convertVec.
No nothing has changed. I only deleted a few comment lines. And I'm not referring to the warnings. They are self-explanatory.
I have to use char because I'm handeling a dirent structure on a UNIX system to get a file tree.

The linking error is exactly my point.
I split the .h in to .cpp and .h and now get this.
The function convertVec does exist in scope as you can see on top.
The implementation of function templates has to be available when they are used so you have to define convertVec in the header. Templates are special so you will not get a multiple definition errors by doing so.

To get rid of the warning you should at least put a const.
 
const char *workingDir="./data";

It is often no problem using std::string with functions expecting C strings because you can use c_str() to get a const char* from a std::string.
http://www.cplusplus.com/reference/string/string/c_str/
For templates, you need to keep the function definitions in the header file. This is because the class is created by the compiler at compile-time from the template and its parameters, so the entirety of the template definition needs to be included in the header.

The other functions need to have their definitions in the .cpp file.
Thanks I forgot all about the template.
Yes I know how to solve the warnings. I'm more focussed on functionality rather elegance atm. =)

Thanks =)
Topic archived. No new replies allowed.