0

gcc version 5.4.0 (GCC)

> g++ -std=c++11

During a build I get a multiply defined error message for a class constructor. When I delete the constructor, I get an undefined symbol error message. I'm stumped.

NodeClass::NodeClass( ... ) is marked as

Error Message:

build/Debug/Cygwin64-Windows/nodeClass.o: In function `__gnu_cxx::new_allocator<std::string*>::~new_allocator()':
/c/home/skidmarks/Projects/MPHASH/mphash/NodeClass.cpp:36: multiple definition of `NodeClass::NodeClass(std::vector<std::string*, std::allocator<std::string*> >&)'

build/Debug/Cygwin64-Windows/NodeClass.o:/c/home/skidmarks/Projects/MPHASH/mphash/NodeClass.cpp:36: first defined here

Header file:

# include <vector>
# include <gslip/SlipPointer.h>

class NodeClass : public SlipPointer 
{
private:
   vector<string*> vec;
public:
   NodeClass(vector<string*>& vec);
   virtual ~NodeClass() { };
private:
   NodeClass(const NodeClass& orig) { };
};

Source Code:

# include <vector>
# include "NodeClass.h"

using namespace std;
using namespace slip;

NodeClass::NodeClass(vector<string*>& vec) :
   SlipPointer(new string("Cluster Node")), vec(vec) {}
Cœur
  • 37,241
  • 25
  • 195
  • 267
lostbits
  • 928
  • 1
  • 9
  • 23
  • 9
    Missing header include guards? – user0042 Aug 13 '17 at 20:10
  • This might be helpful. https://stackoverflow.com/questions/12573816/what-is-an-undefined-reference-unresolved-external-symbol-error-and-how-do-i-fix. – R Sahu Aug 13 '17 at 20:29
  • @user0042 : Guards are there. @ R Sahu: Link deals with undefined symbols. this is a double defined symbol. – lostbits Aug 13 '17 at 21:03
  • @ArthurSchwarez Provide a [MCVE] please. – user0042 Aug 13 '17 at 21:04
  • @ArthurSchwarez - you have _not_ shown 'header include' guards in your code snippets, not in either file. Are you suggesting they are in your code? If so, why did you not include them? Header guards are of a developer choice format. For file NodeClass.h, mine would be "#ifndef NODECLASS_H". – 2785528 Aug 13 '17 at 22:22
  • I have just failed to compile an old, working program. It failed on an I/O statement.. I am using the Netbeans IDE vs 8.2. An attempt to create a simple example of this problem failed with different errors a\than the multiply defined error. At this stage I don't understand the problem enough. I will continue with this monster until I understand it enough to say I don't understand something. Sorry @moen about the imprecision. I glossed over the obvious. – lostbits Aug 14 '17 at 19:38
  • I notice it's trying to build both a "nodeClass.o" and a "NodeClass.o". You might want to check your source code filenames. – aschepler Sep 03 '17 at 15:03

2 Answers2

0

You have not provided sufficient info to confidently identify your compile error. I agree it is possible that a double definition might happen without sufficient and appropriate include guards. You have shown no include guards, and your error is not evident in the above code,


There are 2 types of include guards. I have seen both used, but less often at the same time. All are examples of conditional compile commands.

In the header file with name "NodeClass.h", my version of the header guard would have the first 2 and last line (examples of conditional compilation) of the following:

#ifndef  NODECLASS_H     // <--- header include guard
#define  NODECLASS_H     // <---
#include <vector>
#include <gslip/SlipPointer.h>

class NodeClass : public SlipPointer 
{
   private:
      vector<string*> vec;
   public:
      NodeClass(vector<string*>& vec);
      virtual ~NodeClass() { };
   private:
      NodeClass(const NodeClass& orig) { };
};
#endif                   // <---

In the code file, name "NodeClass.cc", my 2nd version of the header guard would include similar conditional compilation statements. This is less used in most environments, and I prefer the above.

#ifndef NODECLASS_H   
#include "NodeClass.h"
#endif
#include <vector>     // <-- redundant since also in header

using namespace std;
using namespace slip;

NodeClass::NodeClass(vector<string*>& vec) 
   : SlipPointer(new string("Cluster Node"))
   , vec(vec) 
{
}
2785528
  • 5,438
  • 2
  • 18
  • 20
  • 1
    Why would you test the include guard in the .cc file ? – M.M Aug 13 '17 at 23:05
  • @M.M paranoia? you do not have permission to modify the .h file (politics?) you have an order to do so (pointy hair manager - I've not met one, but I suppose they do exist) My imagination fails me. – 2785528 Aug 14 '17 at 02:51
  • 1
    @SahibYar - If separate compilation units both define "anything()' (by including the OP's same header), and these 2 (or more) compilation unit outputs are subsequently linked together, this will indeed result in multiple definition error, for which include guards offer no solution. The example in that question shows a header file with a definition of "anything()", not just the declaration of "anything()". Review: declaration vs definition (i.e. header vs code). The error is that header file with a definition pulled into multiple compilation units AND linked. – 2785528 Aug 14 '17 at 03:06
  • @SahibYar - w.r.t your ref: A) the linker detects violations of the ODR (One Definition Rule) B) a function definition placed in a header with any number of declarations is still a definition C) '#include' makes copies – 2785528 Aug 14 '17 at 14:26
  • @moen thanks for pointing out another header guard. I learned! Mind you, I can't ever think of using it, but I wouldn't know that "I'd never think of using it" without you telling me what "it" was. thanks – lostbits Sep 04 '17 at 19:42
  • @M.M - w.r.t. .cc 'guards': in general, compilers can not rule out that some #define (such as an include guard definition, or, for example the assert macro) has changed since the previous read. I think the .cc include guard allows the programmer to handle this kind of issue. Not reading an include file has got to be faster than reading it, right? So perhaps the idea was better performance. Have you ever calculated how much text the #includes cause to be read? On a big build, it was _big_ (many Gigabytes), and difficult (but not impossible) to determine, Done that. – 2785528 Sep 05 '17 at 13:30
0

I suspect you have out-of-line definitions of these functions in you header.

Initialization list is part of constructor's definition so you need to define it at the same place you define constructor's body. This means that you should have to do it in your header file:

NodeClass(vector<string*>& vec) :
   SlipPointer(new string("Cluster Node")), vec(vec) {}

Since the definition of the constructor is not inline in the class definition, the compiler does not make it implicitly inline. Now, if you include the same file in multiple translation units (i.e. *.cpp files), the linker will produce exactly the error you see, because each of the *.cpp files will contain its own definition of the constructor without them being marked as inline functions.

Alternate easy solution is just to put a inline in front of the constructor declaration:

public:
   inline NodeClass(vector<string*>& vec);
Sahib Yar
  • 1,030
  • 11
  • 29