views:

691

answers:

2

I have the below code in stdafx.h.

using namespace std;

typedef struct {
    DWORD address;
    DWORD size;
    char file[64];
    DWORD line;
} ALLOC_INFO;

typedef list<ALLOC_INFO*> AllocList;
//AllocList *allocList;

Without the commented code (last line), it compiles just fine. But when I add the commented code, Im getting the following error.

error LNK2005: "class std::list > * allocList" (?allocList@@3PAV?$list@PAUALLOC_INFO@@V?$allocator@PAUALLOC_INFO@@@std@@@std@@A) already defined in test.obj

Im using Visual Studio .NET 2003. Anyone has any idea what that is and how to solve it?

+11  A: 

Don't put definitions in header files, just declarations. Declarations specify that something exists while definitions actually define them (by allocating space). For example typedef, extern and function prototypes are all declarations, while things like struct, int and function bodies are definitions.

What's happening is that you're most likely including stdafx.h in multiple compilation units (C++ source files) and each of the resulting object files is getting its own copy of allocList.

Then when you link the objects together, there's two (or more) things called allocList, hence the link error.

You would be better off declaring the variable:

extern AllocList *allocList;

in your header file and defining it somewhere in a C++ source file (such as a main.cpp):

AllocList *allocList;

That way, every compilation unit that includes stdafx.h will know about the external variable, but it's only defined in one compilation unit.

Based on your further information:

I was trying to follow http://www.flipcode.com/archives/How_To_Find_Memory_Leaks.shtml, I assume that all those code are meant to be placed in the stdafx.h. Any other alternatives, pax?

My response is as follows.

I wouldn't put them in stdafx.h myself since I think that uses some MS magic for pre-compiled headers.

Make a separate header file mymemory.h and put your function prototypes in it, for example (note that this has no body):

inline void * __cdecl operator new(
    unsigned int size,
    const char *file,
    int line);

Also in that header, put the other prototypes for AddTrack(), DumpUnfreed(), etc., and the #define, typedef and extern statements:

extern AllocList *allocList;

Then, in a new file mymemory.cpp (which also contains #include "mymemory.h"), put the actual definition of allocList along with all the real functions (not just the prototypes) and add that file to your project.

Then, #include "mymemory.h" in every source file in which you need to track memory (probably all of them). Because there are no definitions in the header file, you won't get duplicates during the link and because the declarations are there, you won't get undefined references either.

Keep in mind that this won't track memory leaks in code that you don't compile (e.g., third-party libraries) but it should let you know about your own problems.

paxdiablo
A: 

I was trying to follow this article, I assume that all those code are meant to be placed in the stdafx.h. Any other alternatives pax?

RWendi
This should really have been a comment to my answer (so I get notified) but I'll answer it anyway. That code will work if there's a single C++ source file including stdafx.h. Otherwise it'll get link errors - I suspect it was never tested in a real installation with multi-files.
paxdiablo
Suggest you email the author (dpicco -at- cs.mun.ca) to see what they're on about.
paxdiablo
For a suggested fix, see my answer. Basically all the functions and allocList definition should be in a separate C++ source file, you can leave the function prototypes and an extern marker for allocList in stdafx.h (although you may want to move them to another header file).
paxdiablo