Question

I am getting these errors:

Error   2   error LNK2005: "class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > __cdecl ToString(int)" (?ToString@@YA?AV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@H@Z) already defined in Sender.obj C:\CSE687\Project3_TT_1\Repository\Repository.obj

Error   3   error LNK2005: "private: static int Sender::count" (?count@Sender@@0HA) already defined in Sender.obj   C:\CSE687\Project3_TT_1\Repository\Repository.obj

Error   4   error LNK1169: one or more multiply defined symbols found   C:\CSE687\Project3_TT_1\Debug\Repository.exe

from these three pieces of code:

#ifndef SEND_H
#define SEND_H
/////////////////////////////////////////////////////////////////
// Sender.cpp - Demonstration of concurrent socket connectors  //
// ver 2                                                       //
// Jim Fawcett, CSE687 - Object Oriented Design, Spring 2013   //
/////////////////////////////////////////////////////////////////
/*
 * This Sender expects to write lines of text only.
 * So message framing is done by lines.  
 *
 * For HTTP like protocols the Sender should send lines for each
 * header attribute and bytes in the body, if there is one,
 * specified by a last header line something like:
 *    content_length : 1024
 * where 1024 is a stand-in for whatever you want your block 
 * size to be.
 *
 */
/*
 * Required files:
 * - Sender.cpp, Sockets.h, Sockets.cpp, 
 *   Threads.h, Threads.cpp, Locks.h, Locks.cpp
 *   BlockingQueue.h, BlockingQueue.cpp
 *
 * Maintanence History:
 * ver 1.1 - 30 Mar 2013
 * - changed Sendthread from terminating to default
 * - minor changes to error handling
 * ver 1.0 - 29 Mar 2013
 * - first release
 */

#include "../sockets/Sockets.h"
#include "../Threads/Threads.h"
#include "../Threads/Locks.h"
#include "../BlockingQueue/BlockingQueue.h"

#include <string>
#include <iostream>
#include <sstream>

///////////////////////////////////////////////////
// SendThread thread



class SendThread : public threadBase
{
public:
  SendThread(Socket s, BlockingQueue<std::string>& q) : s_(s), q_(q) {}
  std::string& status() { return status_; }
private:
  void run()
  {
    status_ = "good";
    doLog("send thread running");
    std::string msg;
    do
    {
      doLog("send thread enqing msg");
      msg = q_.deQ();
      if(!s_.writeLine(msg))
      {
        sout << "\n  bad status in sending thread";
        status_ = "bad";
        break;
      }
    } while(msg != "stop");
    s_.disconnect();
  }
  std::string status_;
  Socket s_;
  BlockingQueue<std::string>& q_;
};


std::string ToString(int i)
{
  std::ostringstream conv;
  conv << i;
  return conv.str();
}



class Sender
{
public:
    Sender() {};
    Sender(int numMsgs) : numMsgs_(numMsgs) { myCount = ++count; }
  int id() { return myCount; }
  void start(std::string ip, int port)
  {
    sout << locker << "\n Sender #" << id() << " started" << unlocker;
    pSt = new SendThread(s_, q_);
    pSt->start();
    if(!s_.connect(ip, port))
    {
      sout << locker << "\n  couldn't connect to " << ip << ":" << port << "\n\n" << unlocker;
      delete pSt;
      return;
    }
    else
    {
      std::string logMsg = "\n  connected to " + ip + ":" + ToString(port);
      doLog(logMsg.c_str());
    }
    doLog("starting Sender");
    std::string msg;
    for(int i=0; i<numMsgs_; ++i)
    {
      doLog("sending message");
      msg = "sender#" + ToString(id()) + ": msg#" + ToString(i);
      sout << locker << "\n  " << msg.c_str() << unlocker;
      q_.enQ(msg);
      ::Sleep(10 * id());  // sleep time increases with each addition Sender
      if(pSt->status() == "bad")
        break;
    }
    q_.enQ("stop");
    msg = "sender#" + ToString(id()) + ": stop";
    sout << "\n  " + msg;
    pSt->join();
    delete pSt;
  }
private:
  Socket s_;
  BlockingQueue<std::string> q_;
  SendThread* pSt;
  static int count;
  int myCount;
  int numMsgs_;
};

int Sender::count = 0;

///////////////////////////////////////////////////
// DemoThread is used to get two or more senders
// running concurrently from a single process, to
// make testing easier.

class DemoThread : public threadBase
{
public:
  DemoThread(Sender sndr) : sndr_(sndr) {}
private:
  void run()
  {
    sndr_.start("127.0.0.1", 8080);
  }
  Sender sndr_;
};

#endif

and:

#ifndef REPOS_H
#define REPOS_H
/////////////////////////////////////////////////////////////////
// Recepository.h - Demonstration of repository action using a //
//  socket reciever with concurrent clients                    //
//                                                             //
// Thomas P. Taggart                                           //
// tptaggarsyr.edu                                             //
// CSE687, Object Oriented Design, Spring 2013                 //
/////////////////////////////////////////////////////////////////

/*
 * Required files:
 * - Reciever.h, Receiver.cpp, Sockets.h, Sockets.cpp, 
 *   Threads.h, Threads.cpp, Locks.h, Locks.cpp
 *   BlockingQueue.h, BlockingQueue.cpp

 */
#include "../Sockets/Sockets.h"
#include "../Threads/Threads.h"
#include "../Threads/Locks.h"
#include "../Receiver/Receiver.h"
#include "../Sender/Sender.h"
#include "../BlockingQueue/BlockingQueue.h"
#include <string>



class Repository
{

public:

    Repository() {};
    ~Repository() {};

    Sender* getSender();
    Receiver* getReceiver();

private:

    Sender* repoSender;
    Receiver* repoReceiver;


};


#endif

and:

/////////////////////////////////////////////////////////////////
// Recepository.cpp - Demonstration of repository action using //
//  a socket reciever with concurrent clients                  //
//                                                             //
// Thomas P. Taggart                                           //
// tptaggarsyr.edu                                             //
// CSE687, Object Oriented Design, Spring 2013                 //
/////////////////////////////////////////////////////////////////

/*
 * Required files:
 * - Reciever.h, Receiver.cpp, Sockets.h, Sockets.cpp, 
 *   Threads.h, Threads.cpp, Locks.h, Locks.cpp
 *   BlockingQueue.h, BlockingQueue.cpp

 */


#include "../Repository/Repository.h"
#include <string>

using namespace std;


Sender* Repository::getSender()
{
    return repoSender;
}

Receiver* Repository::getReceiver()
{
    return repoReceiver;
}



int main()
{
    int ret = 0;
    try
    {
        Repository repos;
        repos.getReceiver()->start(8080);
    }
    catch(std::exception& ex)
    {
        std::cout << "\n\n  " << ex.what();
        ret = 1;
    }
    catch(...)
    {
        sout << "\n  something bad happened";
        ret = 1;
    }
    sout << "\n\n";
    return ret;
}

I have not for the life of me been able to figure out how to avoid it. the 'extern' solution doesn't seem to work and #ifndef headers area already used.

Any advice is greatly appreciated.

Tom

Was it helpful?

Solution

You're breaking the ODR - either make std::string ToString(int i) inline or move it to an implementation file.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top