Declaration of struct in header file used by multiple files causes duplicate symbol for architecture x86_64 [duplicate]
Asked Answered
S

2

5

Even though I have included header guards on all my header files, when I create a header file PointXYZRGBAI.h and include it in both LidarFile.cpp and core.cpp, an error is generated

duplicate symbol _EIGEN_ALIGN_16 in:
    CMakeFiles/core.dir/core.cpp.o
    CMakeFiles/core.dir/LidarFile.cpp.o
ld: 1 duplicate symbol for architecture x86_64

and the header the error seems to be complaining about is

#define PCL_NO_PRECOMPILE

#ifndef POINTXYZRGBAI_H
#define POINTXYZRGBAI_H
#endif

#include <pcl/point_types.h>

struct PointXYZRGBAI{
  PCL_ADD_POINT4D;
  union{
    struct{
      float intensity;
      uint32_t rgba;
    };
    float data_c[4];
  };
  EIGEN_MAKE_ALIGNED_OPERATOR_NEW
} EIGEN_ALIGN_16;

POINT_CLOUD_REGISTER_POINT_STRUCT(PointXYZRGBAI,
                                  (float, x, x)
                                  (float, y, y)
                                  (float, z, z)
                                  (float, intensity, intensity)
                                  (uint32_t, rgba, rgba)
)

inline std::ostream& operator << (std::ostream& os, const PointXYZRGBAI& p){
  os << "(" << p.x << ", " << p.y << ", " << p.z << " - " << p.intensity << " - " << p.rgba << ")";
  return (os);
}

and I use EIGEN_ALIGN_16 in my header defined struct for memory alignment. Why is EIGEN_ALIGN_16 a duplicate symbol if a header guard should prevent multiple inclusions? Thank you for the clarification.

Sumpter answered 20/8, 2016 at 3:21 Comment(2)
In addition to good answers, your endif should be at the end of the header file as otherwise it is useless.Ganley
'Header' files typically have only declarations (a type and a name, aka interface). The definitions (all the details of implementation) typically go into the implementation file, with suffix .c or .cpp.Wesleyanism
C
6

The header guards prevent multiple inclusion of the symbols in a single compilation unit (.o file). However, you've declared an actual variable in the header file, and therefore each compilation unit that includes this header will get its own copy of the variable. This isn't a problem until you link more than one object file containing the symbol together. That's why the problem is reported by ld and not gcc.

A better approach is to put the variable declaration inside a compilation unit (one of the .c or .cpp files) and use extern in the header file to reference that single instance.

This is a problem that trips up even senior software developers.

Crewelwork answered 20/8, 2016 at 3:29 Comment(0)
T
3

The include guard prevents multiple inclusions within the same .cpp file.

However, you're including it in multiple .cpp files. Since that header defines an object (EIGEN_ALIGN_16), it will be included in both, and then the linker will complain that there are two duplicate definitions.

Tupler answered 20/8, 2016 at 3:29 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.