7 Replies - 2700 Views - Last Post: 01 December 2011 - 10:01 PM Rate Topic: -----

#1 MrJabbaNoHere   User is offline

  • New D.I.C Head

Reputation: 1
  • View blog
  • Posts: 29
  • Joined: 08-March 11

Trouble Compiling with fatal "multiply-defined" errors in UNIX

Posted 01 December 2011 - 08:18 PM

I'm trying to compile 4 files in unix using the command 'g++ driver.cpp BST.h BST.cpp TreeNode.h' and am getting the error:

g++ driver.cpp BST.h BST.cpp TreeNode.h
ld: fatal: symbol `TreeNode::getData() const' is multiply-defined:
(file /tmp/ccRWJGzT.o type=FUNC; file /tmp/ccZaNWUw.o type=FUNC);
ld: fatal: symbol `TreeNode::TreeNode()' is multiply-defined:
(file /tmp/ccRWJGzT.o type=FUNC; file /tmp/ccZaNWUw.o type=FUNC);
ld: fatal: symbol `TreeNode::TreeNode(int)' is multiply-defined:
(file /tmp/ccRWJGzT.o type=FUNC; file /tmp/ccZaNWUw.o type=FUNC);
ld: fatal: symbol `TreeNode::TreeNode()' is multiply-defined:
(file /tmp/ccRWJGzT.o type=FUNC; file /tmp/ccZaNWUw.o type=FUNC);
ld: fatal: symbol `TreeNode::TreeNode(int)' is multiply-defined:
(file /tmp/ccRWJGzT.o type=FUNC; file /tmp/ccZaNWUw.o type=FUNC);
ld: fatal: File processing errors. No output written to a.out
collect2: ld returned 1 exit status

My 4 files are as follows

BST.h:
#include <iostream>
#include "TreeNode.h"
using namespace std;


#ifndef BINARY_SEARCH_TREE
#define BINARY_SEARCH_TREE



class BST
{
public:
	BST();
	~BST();
	bool empty() const;
	bool searchTree(const int & item) const;
        void remove(const int & item);
	void insert(const int & item);
	void preorder(ostream & out) const;
        void inorder(ostream & out) const;
	void postorder(ostream &out) const;
	void graph(ostream & out) const;
	


private:
    typedef TreeNode * TreeNodePointer;
    TreeNodePointer myRoot;

    void search2(const int & item, bool & found, TreeNodePointer & locptr, TreeNodePointer & parent) const;
    void preorderAux(ostream & out, TreeNodePointer subtreePtr) const;
    void postorderAux(ostream & out, TreeNodePointer subtreePtr) const;
    void inorderAux(ostream & out, TreeNodePointer subtreePtr) const;
    void graphAux(ostream & out, int indent, TreeNodePointer subtreeRoot) const;

	

};

#endif






BST.cpp:
#include <iostream>
#include <iomanip>
#include "BST.h"
#include "TreeNode.h"

using namespace std;



BST::BST()
: myRoot(0)
{}

bool BST::empty() const
{ return myRoot == 0;}

bool BST::searchTree(const int & item) const
{
TreeNodePointer locptr = myRoot;
   bool found = false;
   while (!found && locptr != 0)
   {
      if (item < locptr->data)       // descend left
        locptr = locptr->Lchild;
      else if (locptr->data < item)  // descend right
        locptr = locptr->Rchild;
      else                           // item found
        found = true;
   }
   return found;
}

void BST::insert(const int & item)
{
   TreeNodePointer
        locptr = myRoot,   // search pointer
        parent = 0;        // pointer to parent of current node
   bool found = false;     // indicates if item already in BST
   while (!found && locptr != 0)
   {
      parent = locptr;
      if (item < locptr->data)       // descend left
         locptr = locptr->Lchild;
      else if (locptr->data < item)  // descend right
         locptr = locptr->Rchild;
      else                           // item found
         found = true;
   }
   if (!found)
   {                                 // construct node containing item
      locptr = new TreeNode(item);
      if (parent == 0)               // empty tree
         myRoot = locptr;
      else if (item < parent->data )  // insert to left of parent
         parent->Lchild = locptr;
      else                           // insert to right of parent
         parent->Rchild = locptr;
   }
   else
      cout << "Item already in the tree\n";
}

void BST::remove(const int & item)
{
   bool found;                      // signals if item is found
   TreeNodePointer
      x,                            // points to node to be deleted
      parent;                       //    "    " parent of x and xSucc
   search2(item, found, x, parent);

   if (!found)
   {
      cout << "Item not in the BST\n";
      return;
   }
   //else
   if (x->Lchild != 0 && x->Rchild != 0)
   {                                // node has 2 children
      // Find x's inorder successor and its parent
      TreeNodePointer xSucc = x->Rchild;
      parent = x;
      while (xSucc->Lchild != 0)       // descend left
      {
         parent = xSucc;
         xSucc = xSucc->Lchild;
      }

     // Move contents of xSucc to x and change x
     // to point to successor, which will be removed.
     x->data = xSucc->data;
     x = xSucc;
   } // end if node has 2 children

   // Now proceed with case where node has 0 or 2 child
   TreeNodePointer
      subtree = x->Lchild;             // pointer to a subtree of x
   if (subtree == 0)
      subtree = x->Rchild;
   if (parent == 0)                  // root being removed
      myRoot = subtree;
   else if (parent->Lchild == x)       // left child of parent
      parent->Lchild = subtree;
   else                              // right child of parent
      parent->Rchild = subtree;
   delete x;
}

void BST::preorder(ostream & out) const
{
   preorderAux(out, myRoot);
}
void BST::inorder(ostream & out) const
{
   inorderAux(out, myRoot);
}
void BST::postorder(ostream & out) const
{
   postorderAux(out, myRoot);
}

void BST::graph(ostream & out) const
{ graphAux(out, 0, myRoot); }









void BST::search2(const int & item, bool & found,
                            TreeNodePointer & locptr,
                            TreeNodePointer & parent) const
{
   locptr = myRoot;
   parent = 0;
   found = false;
   while (!found && locptr != 0)
   {
      if (item < locptr->data)       // descend left
      {
         parent = locptr;
         locptr = locptr->Lchild;
      }
      else if (locptr->data < item)  // descend right
      {
         parent = locptr;
         locptr = locptr->Rchild;
      }
      else                           // item found
         found = true;
   }
}



void BST::preorderAux(ostream & out, TreeNodePointer subtreeRoot) const
{
   if (subtreeRoot != 0)
   {
      out << subtreeRoot->data << "  ";      // V operation
      preorderAux(out, subtreeRoot->Lchild);    // L operation
      preorderAux(out, subtreeRoot->Lchild);   // R operation
   }
}

void BST::postorderAux(ostream & out, TreeNodePointer subtreeRoot) const
{
   if (subtreeRoot != 0)
   {
      postorderAux(out, subtreeRoot->Lchild);    // L operation
      postorderAux(out, subtreeRoot->Rchild);   // R operation
      out << subtreeRoot->data << "  ";      // V operation
   }
}

void BST::inorderAux(ostream & out, TreeNodePointer subtreeRoot) const
{
   if (subtreeRoot != 0)
   {
      inorderAux(out, subtreeRoot->Lchild);    // L operation
      out << subtreeRoot->data << "  ";      // V operation
      inorderAux(out, subtreeRoot->Rchild);   // R operation
   }
}



void BST::graphAux(ostream & out, int indent, TreeNodePointer subtreeRoot) const
{
  if (subtreeRoot != 0)
    {
      graphAux(out, indent + 8, subtreeRoot->Rchild);
      out << setw(indent) << " " << subtreeRoot->data << endl;
      graphAux(out, indent + 8, subtreeRoot->Lchild);
    }
}





TreeNode.h:
#include <iostream>

#ifndef TREENODE
#define TREENODE

class TreeNode
{
friend class BST;

public:
  TreeNode();  //default constructor
  TreeNode(int item);


  int getData () const; // accessor function

private:
 int data;
 TreeNode * Lchild;
 TreeNode * Rchild;

};

TreeNode::TreeNode()
{
    Lchild = Rchild = NULL;
}

TreeNode::TreeNode(int item)
    : data(item), Lchild(0), Rchild(0)
    {}




int TreeNode::getData() const
{ return data;}


#endif



driver.cpp:
#include <iostream>
#include <iomanip>
#include "BST.h"
#include "TreeNode.h"
using namespace std;

int main()
{
  BST tree;  // Class constructor does initialization
  cout<<"Creating tree with values 5,16,23,3,54,12"<<endl;
  tree.insert(5);
  tree.insert(16);
  tree.insert(23);
  tree.insert(3);
  tree.insert(54);
  tree.insert(12);
  cout<<"Graphical representation of tree:"<<endl;
  tree.graph(cout);
}




NOTE: I believe my code is correct, since when I compile with the command "g++ driver.cpp BST.h BST.cpp TreeNode.h -c" I get NO errors. I think I'm just not compiling it properly.

Thanks for the help!

Is This A Good Question/Topic? 0
  • +

Replies To: Trouble Compiling with fatal "multiply-defined" errors in UNIX

#2 snoopy11   User is offline

  • Engineering ● Software
  • member icon

Reputation: 1555
  • View blog
  • Posts: 4,930
  • Joined: 20-March 10

Re: Trouble Compiling with fatal "multiply-defined" errors in UNIX

Posted 01 December 2011 - 08:51 PM

You do have errors


multiple definitions in TreeNode.h

TreeNode::TreeNode()
{
    Lchild = Rchild = NULL;
}

TreeNode::TreeNode(int item)
    : data(item), Lchild(0), Rchild(0)
    {}


Snoopy
Was This Post Helpful? 0
  • +
  • -

#3 MrJabbaNoHere   User is offline

  • New D.I.C Head

Reputation: 1
  • View blog
  • Posts: 29
  • Joined: 08-March 11

Re: Trouble Compiling with fatal "multiply-defined" errors in UNIX

Posted 01 December 2011 - 08:56 PM

I see, but how am I supposed to have both my default constructor and my explicit value constructor if the compiler sees it as multiply defined?
Was This Post Helpful? 0
  • +
  • -

#4 r.stiltskin   User is offline

  • D.I.C Lover
  • member icon

Reputation: 2034
  • View blog
  • Posts: 5,436
  • Joined: 27-December 05

Re: Trouble Compiling with fatal "multiply-defined" errors in UNIX

Posted 01 December 2011 - 09:16 PM

I can't see why that's happening but I can tell you how to fix it.
Maybe Jim can spot the problem in your code.


Split TreeNode.h into two files, TreeNode.h containing just the class definition and TreeNode.cpp containing the implementation code:

//TreeNode.h
#ifndef TREENODE_H
#define TREENODE_H


class TreeNode
{
    friend class BST;

public:
    TreeNode();  //default constructor
    TreeNode(int item);


    int getData () const; // accessor function

private:
    int data;
    TreeNode * Lchild;
    TreeNode * Rchild;

};

#endif




//TreeNode.cpp

#include "TreeNode.h"
#include <cstring>      // for NULL

TreeNode::TreeNode()
{
    Lchild = Rchild = NULL;
}

TreeNode::TreeNode(int item)
        : data(item), Lchild(0), Rchild(0)
{}


int TreeNode::getData() const
{
    return data;
}



Also, there's no need to #include TreeNode.h in driver.cpp or in BST.cpp since both of those #include BST.h, and BST.h has #include TreeNode.h

Then compile with "g++ driver.cpp BST.cpp TreeNode.cpp"

This post has been edited by r.stiltskin: 01 December 2011 - 09:21 PM

Was This Post Helpful? 0
  • +
  • -

#5 r.stiltskin   User is offline

  • D.I.C Lover
  • member icon

Reputation: 2034
  • View blog
  • Posts: 5,436
  • Joined: 27-December 05

Re: Trouble Compiling with fatal "multiply-defined" errors in UNIX

Posted 01 December 2011 - 09:42 PM

OK, I see what was happening. BST.h #includes TreeNode.h, and driver.cpp #includes BST.h, so when driver.cpp is compiled (and all of the implementation of TreeNode is included in it) the TreeNode code is compiled into driver.o.

But then BST.cpp is compiled, and that also #includes BST.h (and TreeNode.h), then the TreeNode code is also compiled into BST.o.

Then the linker comes along and finds TreeNode in both object files so you get those multiply-defined errors from the linker.

Notice that the header guards don't prevent this: they make sure that the header is included only once in each compilation unit -- but there are two compilation units.

When I split the TreeNode implementation into a separate .cpp file, it is compiled into its own TreeNode.o file (and not into either of the other .o files), eliminating the problem.
Was This Post Helpful? 1
  • +
  • -

#6 jimblumberg   User is offline

  • member icon

Reputation: 5669
  • View blog
  • Posts: 17,407
  • Joined: 25-December 09

Re: Trouble Compiling with fatal "multiply-defined" errors in UNIX

Posted 01 December 2011 - 09:46 PM

First you have a missing destructor. Also when you compile the code don't forget to turn on warnings: "g++ -g -Wall -Wextra driver.cpp BST.cpp TreeNode.cpp". The -g includes debug information into object files the -W directives turn the on the most common warning messages. In your include files the include guards should guard everything, including the include lines, and you should only include files that are actually required, try to never have a "using namespace" clause in a header file.

After adding a dummy destructor your program compiles, with a couple of warnings but no errors. However I had everything in one file.

The warnings were:

Quote

main.cpp||In constructor ‘TreeNode::TreeNode()’:|
main.cpp|24|warning: ‘TreeNode::data’ should be initialized in the member initialization list|
main.cpp|24|warning: ‘TreeNode::Lchild’ should be initialized in the member initialization list|
main.cpp|24|warning: ‘TreeNode::Rchild’ should be initialized in the member initialization list|
main.cpp|54|warning: ‘class BST’ has pointer data members|
main.cpp|54|warning: but does not override ‘BST(const BST&)’|
main.cpp|54|warning: or ‘operator=(const BST&)’|
||=== Build finished: 0 errors, 6 warnings ===|


If I get a chance I will try multiple files.

Jim
Was This Post Helpful? 0
  • +
  • -

#7 GWatt   User is offline

  • member icon

Reputation: 309
  • View blog
  • Posts: 3,105
  • Joined: 01-December 05

Re: Trouble Compiling with fatal "multiply-defined" errors in UNIX

Posted 01 December 2011 - 09:47 PM

You were including the header file TreeNode.h AND compiling it into the executable. Since you include a header file with code the compiler will process it, and then process it again when it compiles TreeNode.h. r.stiltskin's suggestion was spot on. A good rule of thumb that to follow is never include a .c/.cpp file and never compile a .h/.hpp file. If you are doing either of those things chances are you should rethink your compilation process and possibly your code layout.

This post has been edited by GWatt: 01 December 2011 - 09:49 PM

Was This Post Helpful? 0
  • +
  • -

#8 jimblumberg   User is offline

  • member icon

Reputation: 5669
  • View blog
  • Posts: 17,407
  • Joined: 25-December 09

Re: Trouble Compiling with fatal "multiply-defined" errors in UNIX

Posted 01 December 2011 - 10:01 PM

After trying to compile your program, multiple files. You seem to have a circular dependency issue in your TreeNode.h file. Because your include file has non-inline function implementation, these implementations are being seen more than once. To fix this problem either move the functions inside the class definition:
#ifndef TREENODE
#define TREENODE

class TreeNode
{
      friend class BST;

   public:
      TreeNode()
      {
         Lchild = Rchild = NULL;
      }

      TreeNode(int item)
         : data(item), Lchild(0), Rchild(0)
      {}

      int getData() const
      {
         return data;
      }

   private:
      int data;
      TreeNode * Lchild;
      TreeNode * Rchild;

};
#endif


Or move the implementation code into a .cpp file.
#include "treenode.h"
#include <cstdlib>  // Required for null

TreeNode::TreeNode()
{
    Lchild = Rchild = NULL;
}

TreeNode::TreeNode(int item)
    : data(item), Lchild(0), Rchild(0)
    {}

int TreeNode::getData() const
{ return data;}




Jim
Was This Post Helpful? 0
  • +
  • -

Page 1 of 1