2005 link error - already defined in

Hi,

When I compile the code below i have the following error message.

Thanks in advance.

1>Generating Code...
1>Compiling...
1>SimpleMC.cpp
1>Generating Code...
1>Linking...
1>SimpleMCMain2.obj : error LNK2005: "protected: virtual void __thiscall debugFlowTracer::AddFlow(void)" (?AddFlow@debugFlowTracer@@MAEXXZ) already defined in SimpleMC.obj
1>SimpleMCMain2.obj : error LNK2005: "protected: virtual void __thiscall debugFlowTracer::RemoveFlow(void)" (?RemoveFlow@debugFlowTracer@@MAEXXZ) already defined in SimpleMC.obj
1>SimpleMCMain2.obj : error LNK2005: "private: static class debugFlowTracerManager * debugFlowTracerManager::m_Instance" (?m_Instance@debugFlowTracerManager@@0PAV1@A) already defined in SimpleMC.obj
1>C:\MoonDragon\DistanceLearning\cpp\code\Chap2\Debug\Chap2.exe : fatal error LNK1169: one or more multiply defined symbols found
1>Build log was saved at "file://c:\MoonDragon\DistanceLearning\cpp\code\Chap2\Chap2\Debug\BuildLog.htm"
1>Chap2 - 4 error(s), 0 warning(s)
========== Build: 0 succeeded, 1 failed, 0 up-to-date, 0 skipped ==========



SimpleMC.cpp :

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
#include <SimpleMC.h>
#include <Random1.h>
#include <cmath>

#include "FlowTracerManager.h"

// the basic math functions should be in namespace std but aren't in VCPP6
#if !defined(_MSC_VER)
using namespace std;
#endif

double SimpleMonteCarlo2(const PayOff& thePayOff,
                         double Expiry,  
						 double Spot, 
						 double Vol, 
						 double r, 
						 unsigned long NumberOfPaths)
{
	debugFlowTracer flow("SimpleMonteCarlo2");


	double variance = Vol*Vol*Expiry;
	double rootVariance = sqrt(variance);
	double itoCorrection = -0.5*variance;

	double movedSpot = Spot*exp(r*Expiry +itoCorrection);
	double thisSpot;
	double runningSum=0;

	for (unsigned long i=0; i < NumberOfPaths; i++)
	{
		double thisGaussian = GetOneGaussianByBoxMuller();
		thisSpot = movedSpot*exp( rootVariance*thisGaussian);
		double thisPayOff = thePayOff(thisSpot);
		runningSum += thisPayOff;
	}

	double mean = runningSum / NumberOfPaths;
	mean *= exp(-r*Expiry);
	return mean;
}



SimpleMCMain.cpp :

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
#include<SimpleMC.h>
#include<iostream>
#include "FlowTracerManager.h"

using namespace std;

int main()
{

	debugFlowTracer flow("main");

	double Expiry;
	double Strike; 
	double Spot; 
	double Vol; 
	double r; 
	unsigned long NumberOfPaths;

	cout << "\nEnter expiry\n";
	cin >> Expiry;

	cout << "\nEnter strike\n";
	cin >> Strike;

	cout << "\nEnter spot\n";
	cin >> Spot;

	cout << "\nEnter vol\n";
	cin >> Vol;

	cout << "\nr\n";
	cin >> r;

	cout << "\nNumber of paths\n";
	cin >> NumberOfPaths;

	PayOff callPayOff(Strike, PayOff::call);
	PayOff putPayOff(Strike, PayOff::put);

	double resultCall = SimpleMonteCarlo2(callPayOff,
                                          Expiry,                                           
							              Spot, 
							              Vol, 
							              r, 
						                  NumberOfPaths);
	
    double resultPut = SimpleMonteCarlo2(putPayOff,
                                         Expiry,                                           
							             Spot, 
							             Vol, 
							             r, 
						                 NumberOfPaths);

	cout <<"the prices are " << resultCall << "  for the call and " 
                                    << resultPut << " for the put\n";

    double tmp;
    cin >> tmp;

	return 0;

}



FlowTracerManager.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
#ifndef FLOWTRACERMANAGER_H
#define FLOWTRACERMANAGER_H

#include "FlowTracer.h"

class debugFlowTracerManager
{
private:
	std::stack< debugFlowTracer> m_functionStack;
	static debugFlowTracerManager *m_Instance;

public:
	static debugFlowTracerManager *Instance()
	{
		if ( m_Instance == NULL )
			m_Instance = new debugFlowTracerManager();
		return m_Instance;
	}
	void addFlow( debugFlowTracer& cFlow )
	{
		m_functionStack.push( cFlow );
	}
	void removeFlow(debugFlowTracer& cFlow)
	{
		if ( m_functionStack.empty() )
			return;

		// Get the top element
		debugFlowTracer t = m_functionStack.top();

		// Remove it.
		m_functionStack.pop();

		// If there is anything left, add it
		if ( m_functionStack.empty() )
		{
			printf("Flow [%s]:\n", t.Name().c_str() );
			t.PrintStack(0);
		}
		else
			m_functionStack.top().AddSubFlow( t );

	}

private:
	debugFlowTracerManager()
	{
	}
	debugFlowTracerManager(const debugFlowTracerManager& aCopy )
	{
	}
	virtual ~debugFlowTracerManager(void)
	{
	}
};

debugFlowTracerManager *debugFlowTracerManager::m_Instance = NULL;

void debugFlowTracer::AddFlow()
{
	debugFlowTracerManager::Instance()->addFlow( *this );
}

void debugFlowTracer::RemoveFlow()
{
	debugFlowTracerManager::Instance()->removeFlow( *this );
}

#endif 




FlowTracer.h :

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
#ifndef _FLOWTRACER_H_
#define _FLOWTRACER_H_

#include <string>
#include <stack>
#include <vector>

class debugFlowTracer
{
private:
	std::string m_sFlowName;
	std::vector< debugFlowTracer > m_activefunctionStack;
	bool						   m_bRemoved;
protected:
	virtual void AddFlow();
	virtual void RemoveFlow();

public:
	debugFlowTracer(void)
	{
		m_sFlowName = "Unknown";
		m_bRemoved = false;
		AddFlow();
	}

	debugFlowTracer(const char *strFlow)
	{
		m_sFlowName = strFlow;
		m_bRemoved = false;
		AddFlow();
	}
	debugFlowTracer( const debugFlowTracer& aCopy )
	{
		m_sFlowName = aCopy.m_sFlowName;
		std::vector< debugFlowTracer >::const_iterator iter;
		for ( iter = aCopy.m_activefunctionStack.begin(); iter != aCopy.m_activefunctionStack.end(); ++iter )
			m_activefunctionStack.insert( m_activefunctionStack.end(), (*iter) );
	}


	~debugFlowTracer(void)
	{
		if ( !m_bRemoved )
			RemoveFlow();
		m_bRemoved = true;
	}

	std::string Name()
	{
		return m_sFlowName;
	}

	void AddSubFlow( debugFlowTracer& cSubFlow )
	{
		// Just push it on top of the active function stack
		m_activefunctionStack.insert( m_activefunctionStack.end(), cSubFlow );
	}
	void PrintStack(int iLevel)
	{
		std::vector< debugFlowTracer >::iterator iter;
		for ( iter = m_activefunctionStack.begin(); iter != m_activefunctionStack.end(); ++iter )
		{
			for ( int i=0; i<iLevel; ++i )
				putchar ('\t');
			printf("%s\n", (*iter).Name().c_str() );
			(*iter).PrintStack(iLevel+1);
		}
	}
};





#endif
Last edited on
Both your cpp files #include "FlowTracer.h"

This means both your cpp files define the class debugFlowTracer

Then, when your linker goes looking for the definition of this class, it finds one in each of your compiled cpp files, and then it complains.

This is why it is customary not to define a class in a header file, but in a separate cpp file, with only the declaration in the header file.
Hello,

There is no .cpp file for FlowTracer.h and FlowTracerManager.h.

However the body of the member fonctions (that cause the bug) are implemented in FlowTracerManager.h.

These functions are :

debugFlowTracer::AddFlow(void)

debugFlowTracer::RemoveFlow(void)

debugFlowTracerManager * debugFlowTracerManager::m_Instance
I must have not been clear enough.

Those functions have some definition code. This, for example:

1
2
3
4
void debugFlowTracer::AddFlow()
{
	debugFlowTracerManager::Instance()->addFlow( *this );
}


This code must be in ONE cpp file only. Just ONE. Otherwise, you will have defined the same things twice.

How many cpp files is it in? TWO. It is in TWO files. This is bad.

Which cpp files is it in? SimpleMCMain.cpp and SimpleMC.cpp.

How did the repeated code get into those cpp files? It is in the file FlowTracerManager.h, and that file is included in BOTH those cpp files. This means that the code is in BOTH cpp files. This is bad.

Why don't header guards stop that happening? Header guards work on each cpp file individually. Header guards can only stop a header being included more than once in the same cpp file. They have nothing to do with other cpp files.

Is that clear? Yes, thank you, it's very clear. You have a talent for explaining this sort of thing. Would you like a beer?

Yes please.
Last edited on
Ok,

It is fine now.

Thanks.
Topic archived. No new replies allowed.