Solved

Need help with #include...I keep getting a "multiply defined symbols found" error

Posted on 2011-03-03
20
618 Views
Last Modified: 2013-12-14
If you see the previous related questions that I asked I have created a very simple app called "FirstApp", a dialog-based MFC app in VS2008.  It contains FirstAppDlg.cpp, FirstApp.cpp, and Function.cpp (something I added).  The 3 .cpp files each have respective header .h files.

Here's the error message I get....
Linking...
1>Function.obj : error LNK2005: "class std::vector<struct Data,class std::allocator<struct Data> > vData" (?vData@@3V?$vector@UData@@V?$allocator@UData@@@std@@@std@@A) already defined in FirstAppDlg.obj
1>C:\Documents and Settings\Administrator\Desktop\FirstApp\Debug\FirstApp.exe : fatal error LNK1169: one or more multiply defined symbols found

Below I've included the top portion of the 3 .cpp and 3. h files.  I suspect something is wrong with my include statements.  Can someone please show me what I'm doing wrong?
// FirstAppDlg.cpp : implementation file

#include "stdafx.h"
#include "FirstApp.h"
#include "FirstAppDlg.h"
#include "Function.h"


// FirstAppDlg.h : header file

#pragma once


// FirstApp.cpp : 

#include "stdafx.h"
#include "FirstApp.h"
#include "FirstAppDlg.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#endif


// FirstApp.h : 

#pragma once
#ifndef __AFXWIN_H__
	#error "include 'stdafx.h' before including this file for PCH"
#endif
#include "resource.h"		// main symbols


// Function.cpp

#include "stdafx.h"
#include "Function.h"


// Function.h

#pragma once
#include <string> 
#include <math.h>
#include <vector>
#include <fstream>

Open in new window

0
Comment
Question by:shaolinfunk
  • 8
  • 6
  • 4
  • +1
20 Comments
 
LVL 30

Accepted Solution

by:
Zoppo earned 500 total points
ID: 35025809
Hi shaolinfunk,

I guess you have instantiated 'vData' as global variable within one of your headers - is this right?

In this case the problem comes from the fact that this instance is compiled at least twice.

If you want to instance a global variable you must not do it in a header which is included more than once.

To solve the problem declare the variable in the header as 'extern' and instance it within one CPP file, i.e.:

// Function.h
...
extern vector < struct Data > vData; // declaration

Open in new window


// Function.cpp
...
vector < struct Data > vData; // the instance itself

Open in new window


Thus you can access vData from anywhere the function.h is included but it is instantiated only once.

Hope that helps,

ZOPPO
0
 
LVL 3

Expert Comment

by:pasolo
ID: 35025823
Use #pragma one in every header file as first instruction on top.

No need for  
#ifndef __AFXWIN_H__
      #error "include 'stdafx.h' before including this file for PCH"
#endif

These are deprecated and "pragma once does the same job
0
 
LVL 1

Author Comment

by:shaolinfunk
ID: 35025842
pasolo...if you look at my header files in the attached code snippet above...i already have #pragma once in every header at the top (there are only 3 header files involved here)
0
 
LVL 32

Expert Comment

by:sarabande
ID: 35025858
pasolo, #pragma once is proprietary for ms and normal header protections are not deprecated.

the preprocessor statements you posted are not header protection but ms preprocessor code in generated headers which should make sure that stdafx.h was included before that header.

Sara
0
 
LVL 1

Author Comment

by:shaolinfunk
ID: 35025867
zoppo....i don't know whether a variable is global or not....but your solution works...while i see what you did i don't understand this concept of "extern"...what is this?
0
 
LVL 32

Expert Comment

by:sarabande
ID: 35025870
shaolinfunk, look at zoppo's comment. your problem is that you must not define (only declare) variables in header or the linker complains if the header was included in two cpp files.

instead of using extern you may consider moving the vector to a class as member.

Sara
0
 
LVL 1

Author Comment

by:shaolinfunk
ID: 35025880
I defined vector < struct Data > vData in Function.h.  To me I think this means that any function in Function.cpp may access vData.  Does that make it a global variable when only functions defined in Functions.cpp may access it?  And not any functions in the other .cpp files?
0
 
LVL 32

Expert Comment

by:sarabande
ID: 35025886
the extern turns a definition of a variable to a declaration. so the compiler knows what type the variable is but it doesn't reserve memory for it. if you declare variables as extern you need exactly one cpp file where the variable is defined globally that means outside of any function.

Sara
0
 
LVL 3

Expert Comment

by:pasolo
ID: 35025897
Sorry, shaolinfunk you are 100% right.
Are you including namespace std anywhere?


@sarabande: Yeap, but we are dealing with VS here and it is deprecated in VS
0
 
LVL 1

Author Comment

by:shaolinfunk
ID: 35025898
Hi Sara!

Thanks for your comment.  I think I see what you're saying..but in the related questions (that this question is an offspring of) Zoppo made clear that for this simple app of mine, FirstApp, classes were not needed.

Since I do plan on adding more variables in the future I think classes are the way to go.  

Zoppo, I am thinking of re-posting my earlier question and asking if it can be rewritten using classes this time...What do you think?
0
How to improve team productivity

Quip adds documents, spreadsheets, and tasklists to your Slack experience
- Elevate ideas to Quip docs
- Share Quip docs in Slack
- Get notified of changes to your docs
- Available on iOS/Android/Desktop/Web
- Online/Offline

 
LVL 32

Expert Comment

by:sarabande
ID: 35025921
as told if you don't use extern or have the variable a member of a class, it is a definition of a global variable and every cpp file that includes the header would add a further symbol with that name to the list of definitions.

a good way out normally is to have

// functions.h

struct Vdata
{
    static std::vector < struct Data > vData;
};

// functions.cpp

 ...
 std::vector < struct Data > Vdata::vData;


then everyone can use the vector by including functions.h and like

   Vdata::vData.push_back(data);

Sara
0
 
LVL 30

Expert Comment

by:Zoppo
ID: 35025924
I think you should try to understand how compiler and linker work together to understand what happens here:

The compiler compiles each CPP file in your project - before this is done the preprocessor processes every #include/#define/#ifdef/a.s.o. so in fact the compiler finally compiles one single file which contains everything included in the CPP file. Now, including a header with a instantiated variable into two CPP files leads to two identically instantiated variables. After compiling finished the linker tries to collect all information to put it into the binary (EXE or LIB or DLL) and finds two variables with the same name, so it generates the error.

Using 'extern' tells the compiler 'this is not the instance itself but there exist an instance anywhere', so the compiler generates code wherever the variable is accessed correctly and the linker later can resolve all these accessing code to that one and only instance.

> I am thinking of re-posting my earlier question and asking if it can be rewritten using classes this time...What do you think?
In general I agree, but before you decide this finally I would suggest you think a little bit about what your final goal is in order to find best decision about how your project/code should be designed. If you want you can simply tell us here what you expect your program to be at the end, then we can give you hints on how we would implement it ...
0
 
LVL 32

Expert Comment

by:sarabande
ID: 35025955
pasolo, 'deprecated' means that you shouldn't use a function or technique cause further versions may not support the feature and fail.

the header protections with preprocessor statements is standard C++ and standard C and therefore cannot be deprecated (and i doubt that you can bring evidence that ms named it that way). that means it will always work also in future versions of vc.

your suggestion only works with ms compilers and you shouldn't use it if you ever want to program on other platforms.

Sara
0
 
LVL 30

Expert Comment

by:Zoppo
ID: 35025956
It's hard to say which way is the best to implement this. I for myself don't like to implement something in a class (or struct, which is mostly the same as a class) if this class doesn't have any members and only class-global (static) functions. In this case I decide to implement this globally but within a namespace. There's not much difference between the implementation and IMO none has dis-/atvantages. For example I would implement what sarabande posted like this:

// functions.h

namespace Vdata
{
    extern std::vector < struct Data > vData;
};

// functions.cpp

 ...
 std::vector < struct Data > Vdata::vData;


then everyone can use the vector by including functions.h and like

Vdata::vData.push_back(data);


but I guess that's mostly a matter of ones gusto :o)
0
 
LVL 1

Author Comment

by:shaolinfunk
ID: 35025958
Sara...I think I get a vague sense of what you just did there..making it accessible by taking my vector and putting it in a struct again.  This added layer is tasking my brain's ability to keep track of what's going on but I do see what you did there...Given how I am just doing really, really simple things with my first application I want to simplify as much as possible and not have to keep track of these "twists".

Zoppo...my final goal is to read some numbers and apply a series of calculations to them and have it output to my dialog.  Nothing fancy.  This is my first dialog based app and I would like to proceed accordingly. While I see how you experienced programmers are coming up with solutions, I would like to restrict the solutions to those that would be done by a student teaching himself VC++ from a book.

As such, I would like to learn how to re-write my previous program using classes.  This will be a good exercise for me and I will post a new question.  THANK YOU ALL FOR YOUR CONTRIBUTIONS! Each new post is a new concept that adds to my growth and learning.  I really do appreciate it!
0
 
LVL 1

Author Comment

by:shaolinfunk
ID: 35025967
Btw, Sara I did not mean to sound dismissive of your solution in my last post.  What I should have said was first, Thank you. And second, I am too noob to fully understand and utilize it yet, and would like to keep things as simple as possible.  Soon,  I will post another question regarding classes.  Thanks again!
0
 
LVL 32

Expert Comment

by:sarabande
ID: 35025982
i think you should think about whether functions.h should provide a vector at all.

functions.h will - if the name is well-chosen - provide a number of functions. in my opinion that concept doesn't need a global array of elements of a structure.

Sara

0
 
LVL 30

Expert Comment

by:Zoppo
ID: 35026028
@shaolinfunk: That's great! In fact I think EE is a wonderful place for both begginers and professionals to learn a lot and I appreciate it very much if someone says 'I like to learn how to do something' instead of 'give me a solution, no matter if I understand it'.

BTW, maybe you didn't yet see the articles zone. For beginners there are some interesting articles too, especially for starting dialog programming with MFC I would suggest you should take a look at http://www.experts-exchange.com/Programming/System/Windows__Programming/MFC/A_3707-Sudoku-a-complete-MFC-application-Part-1.html - it's much to read but contains a lot of interesting and essential information.

Further maybe you can find interesting sites in the web with google when search for 'tutorial MFC dialog'.
0
 
LVL 1

Author Comment

by:shaolinfunk
ID: 35026040
Here is the link to my new question:

http://www.experts-exchange.com/Programming/Editors_IDEs/C_CPP_CS/Visual_CPP/Q_26860757.html


Sara,

I am going to have a set a numbers (array of structs) that I need all of my upcoming functions to have access.  Making it global seems the easiest way to do it...is there a better way?
0
 
LVL 1

Author Comment

by:shaolinfunk
ID: 35026165
Zoppo, Thanks for that Sudoku link...I am reading it now.
0

Featured Post

Better Security Awareness With Threat Intelligence

See how one of the leading financial services organizations uses Recorded Future as part of a holistic threat intelligence program to promote security awareness and proactively and efficiently identify threats.

Join & Write a Comment

Programmer's Notepad is, one of the best free text editing tools available, simply because the developers appear to have second-guessed every weird problem or issue a programmer is likely to run into. One of these problems is selecting and deleti…
Go is an acronym of golang, is a programming language developed Google in 2007. Go is a new language that is mostly in the C family, with significant input from Pascal/Modula/Oberon family. Hence Go arisen as low-level language with fast compilation…
The goal of the video will be to teach the user the difference and consequence of passing data by value vs passing data by reference in C++. An example of passing data by value as well as an example of passing data by reference will be be given. Bot…
The viewer will learn additional member functions of the vector class. Specifically, the capacity and swap member functions will be introduced.

759 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

18 Experts available now in Live!

Get 1:1 Help Now