2010-07-19

Visual C++ - symbol already defined, one or more multiply defined symbols found

Wpis będzie dotyczyć Visual C++ 2010, ale prawie na pewno wszystko odnosi się też do poprzednich wersji Visual-a.

Oba tytułowe błędy występują zawsze razem.

Żeby zrozumieć istotę tych błędów trzeba mniej więcej wiedzieć jak budowany jest kod wynikowy w C++. Musimy wiedzieć co robi preprocesor z plikami h, jak powstają obj, co zawierają, co to są biblioteki statyczne, co robi linker z plikami obj i bibliotekami statycznymi. Więcej tutaj:
I jeszcze o sygnaturach:
Poniżej lista przyczyn, które do tytułowych błędów prowadzą. Nie jest ona pewnie kompletna, ale mam nadzieje, że zawiera wszystkie najpopularniejsze przyczyny.

Poniższe przypadki odnoszą się do błędów związanych z symbolami w naszym kodzie, dalej są omówione przypadki błędów związanych z symbolami z bibliotek CRT i MFC.

Podwójna definicja symbolu (funkcja, zmienna)


Linker poszukuje eksportu symbolu dla powiązania go z jego importem i znajduje wiele eksportów o takiej samej syngaturze. Mogą się one znajdować w obj-tach, albo importowanych lib-ach. Po pierwsze możemy oznaczyć symbole używane tylko lokalnie w plikach cpp jako static, dzięki temu nie będą one eksportowane. Po drugie możemy zmienić nazwę spornych symboli.

Deklaracja symbolu w pliku nagłówkowym


Problem pojawia się kiedy taki plik nagłówkowych zostanie dołączony do conajmniej dwóch różnych plików cpp. Rozwiązanie to pozostawienie deklaracji symbolu w pliku nagłówkowym i przeniesienie definicji do pliku cpp. W przypadku funkcji możemy w ostateczności oznaczyć je jako inline.

Plik nagłówkowy dołączany jest wielokrotnie


Dopisz na początku pliku nagłówkowego #pragma once.

Brak #include <afx.h>


Teraz załóżmy, że nasza solucja składa się z projektu pliku wykonywalnego i dołączanej do niej biblioteki statycznej z innego projektu w solucji. Taka przykładowa solucja jest używana dalej w artykule.

Opcje projektów General|Character Set są zgodne. Jeśli do projektu pliku wykonywalnego nie dołączymy afx.h to dostaniemy błędy w zależności od Character Set:

3>uafxcwd.lib(afxmem.obj) : error LNK2005: "void * __cdecl operator new(unsigned int)" (??2@YAPAXI@Z) already defined in LIBCMTD.lib(new.obj)
3>uafxcwd.lib(afxmem.obj) : error LNK2005: "void __cdecl operator delete(void *)" (??3@YAXPAX@Z) already defined in LIBCMTD.lib(dbgdel.obj)

2>nafxcwd.lib(afxmem.obj) : error LNK2005: "void * __cdecl operator new(unsigned int)" (??2@YAPAXI@Z) already defined in LIBCMTD.lib(new.obj)
2>nafxcwd.lib(afxmem.obj) : error LNK2005: "void __cdecl operator delete(void *)" (??3@YAXPAX@Z) already defined in LIBCMTD.lib(dbgdel.obj)


Błędów może być mniej albo więcej, zależy ile potencjalnie konfliktowych symboli użyliśmy. Oczywiście aby uzyskać takie błędy projekt pliku wykonywalnego nie może korzystać z MFC.

Niezgodność opcji projektów


Podejrzane opcje projektów to General|Use of MFC, General|Character Set i C++|Code Generation|Runtime Library. W zależności od ich kombinacji błędy będą różne. Oto niektóre podejrzane komunikaty:

1>LINK : warning LNK4098: defaultlib 'nafxcwd.lib' conflicts with use of other libs; use /NODEFAULTLIB:library

1>msvcrtd.lib(ti_inst.obj) : error LNK2005: "private: __thiscall type_info::type_info(class type_info const &)" (??0type_info@@AAE@ABV0@@Z) already defined in LIBCMTD.lib(typinfo.obj)
1>msvcrtd.lib(ti_inst.obj) : error LNK2005: "private: class type_info & __thiscall type_info::operator=(class type_info const &)" (??4type_info@@AAEAAV0@ABV0@@Z) already defined in LIBCMTD.lib(typinfo.obj)
1>LINK : warning LNK4098: defaultlib 'msvcrtd.lib' conflicts with use of other libs; use /NODEFAULTLIB:library

1>LINK : warning LNK4098: defaultlib 'mfc100u.lib' conflicts with use of other libs; use /NODEFAULTLIB:library
1>LINK : warning LNK4098: defaultlib 'mfcs100u.lib' conflicts with use of other libs; use /NODEFAULTLIB:library
1>LINK : warning LNK4098: defaultlib 'msvcrt.lib' conflicts with use of other libs; use /NODEFAULTLIB:library


Dla uniknięcia tego rodzaju błędów wspomniane wcześniej opcje powinny zostać ujednolicone.

Trochę więcej informacji na temat dwóch ostatnich przyapdków A LNK2005 error occurs when the CRT library and MFC libraries are linked in the wrong order in Visual C++

Brak komentarzy:

Prześlij komentarz