0

I have a 3 source files. The main file has a function that use if statements to define a pointer:

main(int dispersalfn) {

if(dispersalfn == 0) {
    kernel1 = flatdisp;
  } else if(dispersalfn == 1) {
    kernel1 = expdisp;
  }

 [...more stuff...]

}

In main.h I have a definition for kernel1:

arma::vec (*kernel1)(arma::vec d, arma::vec m);

In disp.cpp I have definitions for flapdisp and expdisp:

arma::vec flatdisp(arma::vec d, arma::vec m) {
  return m;
}

arma::vec expdisp(arma::vec d, arma::vec m) {
  return (square(m) / (2*M_PI)) % exp(-m % d);
}

disp.h has corresponding definitions for flatdisp and expdisp:

arma::vec flatdisp(arma::vec d, arma::vec m);
arma::vec expdisp(arma::vec d, arma::vec m);

Finally upfun.cpp has a number of functions that call kernel1. The functions in upfun are called by main().

When I compile, I get an error:

 duplicate symbol _kernel in upfun.o and main.o for architecture x86_64

All my header files source each other have include guards, so I don't think that's it. The idea is that when I call main(), I include variables to choose which function is used for kernel1. This worked until I broke up my functions into different files. What causes this error?

Noam Ross
  • 5,969
  • 5
  • 24
  • 40
  • Seems to be a linker problem do you use the #ifndef HEADER_H #define HEADER_H you should provide a working example – Leosar Oct 02 '13 at 00:13

1 Answers1

3

I will assume that you meant to say:

duplicate symbol _kernel1 in upfun.o and main.o for architecture x86_64

The linker is complaining that you have defined the symbol (a.k.a. variable) "kernel1" in more than one places.

The problem is that you have defined a variable "kernel1" in a header file main.h. This header file is getting included in more than one .cpp file. Therefore, you have effectively defined "kernel1" in more than one compilation unit.

The solution is simple. Move the definition of "kernel1" to main.cpp instead:

arma::vec (*kernel1)(arma::vec d, arma::vec m);

Update added to address comment:

It was pointed out the symbol "kernel1" is being used from another file as well. In which case,

  1. The definition of "kernel1" still needs to happen in main.cpp as described above.

  2. Add an "extern" declaration of kernel1 in the main.h header file:

    extern arma::vec (*kernel1)(arma::vec d, arma::vec m);
    

This should address your problem.

Peter Varo
  • 11,726
  • 7
  • 55
  • 77
joyjit
  • 216
  • 2
  • 4
  • When I do this, I get the error `upfun.cpp:18: error: ‘kernel1’ was not declared in this scope`. Since the functions in `upfun` require `kernel1` (however it is defined in `main`), it needs to be in the header. Per @Leonardo above, I have `#ifndef HEADER_H #define HEADER_H` include guards in all the header files. – Noam Ross Oct 02 '13 at 00:21
  • @Noam Ross: I have updated my answer to address your comment. – joyjit Oct 02 '13 at 17:35
  • This partially addressed the issue. It eliminated this error, but later, on loading, I got the error `Symbol not found: kernel1`. It turns out I also had to have a default value for `kernel1` declaure in `main.cpp`. – Noam Ross Oct 02 '13 at 17:40
  • "I got the error Symbol not found: kernel1". Noam, this will happen you did *NOT* add the definition of kernel1 in main.cpp. Can you please copy-and-paste the COMPLETE compiler/linker output? – joyjit Oct 02 '13 at 17:55
  • Whoops, my mistake. I didn't do #1 at first. Your update is correct. – Noam Ross Oct 02 '13 at 18:00