Кто-нибудь знает, как исправить ошибку компиляции: LNK2005? (Исходный код внутри) - PullRequest
2 голосов
/ 12 января 2009

У меня есть следующий код в 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;

Без закомментированного кода (последняя строка) он прекрасно компилируется. Но когда я добавляю закомментированный код, я получаю следующую ошибку.

ошибка LNK2005: "class std :: list> * allocList "(? allocList @@ 3PAV? $ list @ PAUALLOC_INFO @@ V? $ allocator @ PAUALLOC_INFO @@@ std @@@ std @@ A) уже определено в test.obj

Я использую Visual Studio .NET 2003. Кто-нибудь знает, что это такое и как ее решить?

Ответы [ 2 ]

13 голосов
/ 12 января 2009

Не помещайте определений в заголовочные файлы, просто объявлений . Объявления указывают, что что-то существует, в то время как определения фактически определяют их (выделяя пространство). Например, typedef, extern и прототипы функций являются объявлениями, а такие вещи, как struct, int и тела функций, являются определениями.

Происходит то, что вы, скорее всего, включаете stdafx.h в несколько модулей компиляции (исходные файлы C ++), и каждый из полученных объектных файлов получает свою собственную копию allocList.

Затем, когда вы связываете объекты вместе, есть две (или более) вещи, называемые allocList, следовательно, ошибка связи.

Вы бы лучше объявив переменную:

extern AllocList *allocList;

в вашем заголовочном файле и , определяя где-нибудь в исходном файле C ++ (например, main.cpp):

AllocList *allocList;

Таким образом, каждая единица компиляции, включающая stdafx.h, будет знать о внешней переменной, но она определена только в одной единице компиляции.

На основании вашей дополнительной информации:

Я пытался следовать http://www.flipcode.com/archives/How_To_Find_Memory_Leaks.shtml, Я предполагаю, что весь этот код предназначен для размещения в stdafx.h. Любые другие альтернативы, чел?

Мой ответ следующий:

Я бы не стал помещать их в stdafx.h сам, так как я думаю, что он использует магию MS для предварительно скомпилированных заголовков.

Создайте отдельный заголовочный файл mymemory.h и поместите в него, например, прототипы ваших функций (обратите внимание, что у него нет body ):

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

Также в этом заголовке поместите другие прототипы для AddTrack(), DumpUnfreed() и т. Д., А также операторы #define, typedef и extern:

extern AllocList *allocList;

Затем в новом файле mymemory.cpp (который также содержит #include "mymemory.h") поместите фактическое определение allocList вместе со всеми реальными функциями (не только прототипами) и добавьте этот файл в свой проект.

Затем #include "mymemory.h" в каждом исходном файле, в котором вам нужно отслеживать память (вероятно, все они). Поскольку в заголовочном файле нет определений, вы не получите дубликаты во время ссылки, а поскольку объявления есть, вы также не получите неопределенные ссылки.

Имейте в виду, что это не будет отслеживать утечки памяти в коде, который вы не компилируете (например, сторонние библиотеки), но он должен сообщать вам о ваших собственных проблемах.

0 голосов
/ 12 января 2009

Я пытался следовать этой статье , я предполагаю, что весь этот код предназначен для размещения в stdafx.h. Любые другие альтернативы pax?

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...