Сообщений 5    Оценка 33        Оценить  
Система Orphus

QnA: error LNK2005: _DllMain@12 already defined ...

Автор: Ivan
Источник: RSDN Magazine #4-2004
Опубликовано: 13.11.2004
Исправлено: 10.12.2016
Версия текста: 1.0

Q. Неужто баг очередной? Создаем ATL проект, в опциях убираем атрибуты, включаем поддержку MFC, включаем Allow merging of proxy/stub code, компилим проект. ВСЕ ок. Закрываем проект. Можно выйти из студии. Открываем опять этот проект, и делаем Rebuild Solution, получаем ошибки:

Linking...
mfcs71d.lib(dllmodul.obj) : error LNK2005: _DllMain@12 already defined in MSVCRTD.lib(dllmain.obj)
mfcs71d.lib(dllmodul.obj) : warning LNK4006: _DllMain@12 already defined in MSVCRTD.lib(dllmain.obj); second definition ignored
Creating library Debug/Minibank.lib and object Debug/Minibank.exp
Debug/Minibank.dll : fatal error LNK1169: one or more multiply defined symbols found

A. Да, это баг в библиотеке MFC (или в CRT) По крайней мере, это справедливо для 7.1, на других версиях не смотрел. Суть проблемы заключается в следующем:

Интересный побочный эффект этой проблемы связан с тем, что проявляться она будет только при определенном порядке просмотра lib'ов линковщиком. Если первой обрабатывается mfcs71 (а так как правило и происходит), то встречая позднее DllMain в CRT линковщик спокойно выбрасывает dllmain.obj и сборка завершается без ошибок. Если же первой будет обрабатываться msvcrt, то встретив позднее DllMain в mfcs71, линковщик уже не сможет исключить dllmodul.obj из процесса сборки и в итоге проект не соберется.

Так происходит в ситуации, которую ты описал. Сразу же после создания проекта ATL+MFC+Merge proxy/stub добавляется модуль "dlldatax.c", который зависит от библиотеки mscvrt, но он обрабатывается последним и при сборке проекта линковщика все проходит "на ура". При последующих сборках он уже обрабатывается первым и, как результат, первой обрабатывается mscvrt.lib и появляется ошибка.

Могу посоветовать 2 вещи:

Q. А почему собственно порядок меняется? От чего это зависит?

A. IMHO, это целиком и полностью зависит от студии. В файле buildlog.html отчетливо видно, что первый раз cl и link вызывается с одним порядком модулей и obj файлов, а второй раз - с другим. Когда link получает список obj файлов - он обрабатывает их по порядку, встречая первым dlldata.obj, он видит зависимость от msvcrt и начинает обрабатывать ее первой, т.е. все зависит от строчки вызова link: если

link.exe dlldata.obj x.obj 

- то будет ошибка, если

link.exe x.obj dlldata.obj, 

то все ok.


Эта статья опубликована в журнале RSDN Magazine #4-2004. Информацию о журнале можно найти здесь
    Сообщений 5    Оценка 33        Оценить