0

I'm using this header file to read textfiles ( I use it to load shader files) and I use it in two different classes.

I'm getting the error Multiple Definition of textFileRead(char*).

Here is the header file:

#ifndef READFILE_H
#define READFILE_H

#include "stdio.h"
#include "stdlib.h"
#include "string.h"
#include "string"
#include "fstream"

char *textFileRead(char *fn) {

FILE *fp;
char *content = NULL;

int count=0;

if (fn != NULL) {
    fp = fopen(fn,"rt");

    if (fp != NULL) {

  fseek(fp, 0, SEEK_END);
  count = ftell(fp);
  rewind(fp);

        if (count > 0) {
            content = (char *)malloc(sizeof(char) * (count+1));
            count = fread(content,sizeof(char),count,fp);
            content[count] = '\0';
        }
        fclose(fp);
    }
}
return content;
}


#endif READFILE_H

what am I doing wrong?

3 Answers3

0

You need to make sure the code from your header file is included once only for each compilation unit. To do this, you put this at the beginning of the file:

#ifndef READFILE_H
#define READFILE_H

and this at the end:

#endif

Of course, the identifier READFILE_H should be unique for each file. Next thing to do is: leave only declarations of your functions and classes in your header, implementations should live in a separate implementation file (.c or .cpp or .cc). So in your header you will have declaration of your function only:

char *textFileRead(char *);

and the definition of your function will be in a separate .c file.

piokuc
  • 25,594
  • 11
  • 72
  • 102
  • OK, so you have the guards. Leave the declaration of your function in the header and move its definition to a separate .c file. – piokuc Nov 25 '12 at 18:15
0

Functions defined in the header need to be marked as inline to prevent multiple definition.

Either this, or separate the implementation to an implementation file.

Include guards guard against multiple definition in the same translation unit, this is a linker problem. The symbol is defined multiple times across translation units.

Luchian Grigore
  • 253,575
  • 64
  • 457
  • 625
0

You're defining the function in the header file, which means that the compiler will make a copy of the same function in each source file where you include this header. When it comes to linking the object files the linker will not know which version to use. (It can not know they are the same, just that their signatures are the same.)

One way to fix this is to move the implementation to a source file, and leave the declaration in the header file, like this:

readfile.h

#ifndef READFILE_H
#define READFILE_H

char *textFileRead(char *fn);

#endif

readfile.cpp

#include "readfile.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <string>
#include <fstream>

char *textFileRead(char *fn) 
{
    FILE *fp;
    char *content = NULL;
    int count=0;

    /* ... code ... */

    return content;
}

Another solution is to mark the function inline and leave the implementation in the header file. Like this:

#ifndef READFILE_H
#define READFILE_H

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <string>
#include <fstream>

inline char *textFileRead(char *fn) 
{
    FILE *fp;
    char *content = NULL;

    /* ... code ... */

    return content;
}

In this last case, the compiler may choose to inline the function where it is called rather than generating a call to it.

It is also possible to use static in place of inline in the above example, or to surround the definition in an anonymous namespace. However neither of these methods are recommended. Unless you have specific reasons you want to potentially inline your function and make its body available in the header file, I'd go for the first alternative.

harald
  • 5,976
  • 1
  • 24
  • 41
  • gentlemen thank you very much. I've never come an error such as this before and it may sounded like a stupid question. None the less much oblige. – Dennis Toufexis Nov 25 '12 at 18:24
  • did I down vote? oh crap I wanted to press the tick button! oh sorry , and I dont have the necessary reputation to change it back. So sorry! – Dennis Toufexis Nov 25 '12 at 18:26
  • Either give an upvote if you think the answer is valuable. If you did vote down, the down arrow next to the score will be colored. Just click it again to undo. Of course if you think it was a bad answer a downvote is allright. A comment so I know why would be helpful, though. – harald Nov 25 '12 at 18:30
  • oh erm I didn't vote you down in the end. I cant vote up or down because I luck the necessary reputation. I don't know who voted you down but I found yours and all the peoples answer here helpful. You just provided something I was missing and that was the "*" in the function declaration. – Dennis Toufexis Nov 25 '12 at 18:34
  • Read all answers. Functions can be defined in a header file just fine, which renders the logic behind your answer wrong. – Luchian Grigore Nov 25 '12 at 18:43
  • The " which means that the compiler will make a copy of the same function in each source file where you include this header." to be exact. This would actually happen if you mark the function `static`, in which case it can still be defined in the header just fine (try it out). – Luchian Grigore Nov 25 '12 at 18:44
  • Was trying to aswer the original posters question, not write a tutorial in C, but I'll update my answer anyways... – harald Nov 25 '12 at 18:50
  • The correct solution is marking it inline. Static, for a function this big, will severely increase code size. No one is asking you for a tutorial in c, but at least don t give out false info. – Luchian Grigore Nov 25 '12 at 19:26
  • I disagree with you there. Inlining a big function is not the way to go. Neither will it decrease code size compared to using just static, quite the contrary. However the question was about why he got linker errors, not about best practices for defining functions in header files. Inline or no inline, static (or anon namespace) is needed anyways to avoid linker errors. – harald Nov 25 '12 at 21:48
  • **NO!** `static` is **not** needed. And shouldn't be used unless really needed. It seems like you don't know the difference between `static` or `inline` or what they do. You have two options - either take the constructive criticism and learn something from my comments, or don't, and keep arguing that you're right (you're not). Your choice. I won't argue about this anymore (not productive for me) – Luchian Grigore Nov 26 '12 at 00:54
  • Also, note that `inline` doesn't inline the function - it's just a hint to the compiler in that sense. The compiler is free to choose - and it probably won't inline it since it's big. Read up on what `inline` actually does. – Luchian Grigore Nov 26 '12 at 00:57
  • @LuchianGrigore, of course I'm open to constructive critisism, and in this case I stand corrected. Hope you're more happy with the answer now. I'm aware that `inline` is a hint, but wasn't aware it changed linkage too. In C the `static` keyword is needed for this case. My mistake. – harald Nov 26 '12 at 12:30
  • That's great! Sorry if that might have bin too harsh. – Luchian Grigore Nov 26 '12 at 15:22