неопределенная ссылка на `WinMain @ 16 ' - PullRequest
99 голосов
/ 10 марта 2011

Когда я пытаюсь построить программу, используя Eclipse CDT, я получаю следующее:

/ MinGW / Библиотека / libmingw32.a (main.o). Main.c :( текст + 0x106): неопределенная ссылка на `WinMain @ 16

Почему это? И как я могу решить эту проблему?

Ответы [ 4 ]

169 голосов
/ 10 марта 2011

Рассмотрим следующую программу уровня Windows API:

#define NOMINMAX
#include <windows.h>

int main()
{
    MessageBox( 0, "Blah blah...", "My Windows app!", MB_SETFOREGROUND );
}

Теперь давайте создадим ее с помощью цепочки инструментов GNU (т.е. g ++), без специальных опций.Здесь gnuc это просто командный файл, который я использую для этого.Он только предоставляет опции, чтобы сделать g ++ более стандартным:

C:\test> gnuc x.cpp

C:\test> objdump -x a.exe | findstr /i "^subsystem"
Subsystem               00000003        (Windows CUI)

C:\test> _

Это означает, что компоновщик по умолчанию создал консольную подсистему .Значение подсистема в заголовке файла указывает Windows, какие службы требуются программе.В этом случае для консольной системы программе требуется окно консоли.

Это также заставляет интерпретатор команд ожидать завершения программы.

Теперь давайте создадим его с Подсистема графического интерфейса , что означает, что программе не требуется консольное окно:

C:\test> gnuc x.cpp -mwindows

C:\test> objdump -x a.exe | findstr /i "^subsystem"
Subsystem               00000002        (Windows GUI)

C:\test> _

Надеемся, что пока все в порядке, хотя флаг -mwindows только частично документирован.

Построение без этого полу-документированного флага нужно было бы более конкретно указать компоновщику, какую подсистему желать получить значение, и тогда в общем случае некоторые библиотеки импорта Windows API должны быть явно указаны:

C:\test> gnuc x.cpp -Wl,-subsystem,windows

C:\test> objdump -x a.exe | findstr /i "^subsystem"
Subsystem               00000002        (Windows GUI)

C:\test> _

Тоработал нормально, с набором инструментов GNU.

Но как насчет набора инструментов Microsoft, то есть Visual C ++?

Хорошо, сборка исполняемого файла консольной подсистемы работает нормально:

C:\test> msvc x.cpp user32.lib
x.cpp

C:\test> dumpbin /headers x.exe | find /i "subsystem" | find /i "Windows"
               3 subsystem (Windows CUI)

C:\test> _

Однако по умолчанию сборка инструментов Microsoft в качестве подсистемы GUI не работает:

C:\test> msvc x.cpp user32.lib /link /subsystem:windows
x.cpp
LIBCMT.lib(wincrt0.obj) : error LNK2019: unresolved external symbol _WinMain@16 referenced in function ___tmainCRTStartu
p
x.exe : fatal error LNK1120: 1 unresolved externals

C:\test> _

Технически это связано с тем, что MicrosoftInker является нестандартным по умолчанию для подсистемы GUI .По умолчанию, когда подсистема имеет GUI, компоновщик Microsoft использует библиотеку времени выполнения точка входа , функцию, с которой начинается выполнение машинного кода, которая называется winMainCRTStartup, которая вызывает нестандартный Microsoft WinMain вместо стандартного main.

Нет ничего сложного в том, чтобы это исправить.

Все, что вам нужно сделать, это сообщить компоновщику Microsoft, какую точку входа использовать, а именно mainCRTStartup, что вызывает стандарт main:

C:\test> msvc x.cpp user32.lib /link /subsystem:windows /entry:mainCRTStartup
x.cpp

C:\test> dumpbin /headers x.exe | find /i "subsystem" | find /i "Windows"
               2 subsystem (Windows GUI)

C:\test> _

Без проблем, но очень утомительно.И настолько загадочные и скрытые, что большинство программистов Windows, которые в основном используют только нестандартные инструменты Microsoft по умолчанию, даже не знают об этом и по ошибке думают, что программа подсистемы Windows GUI «должна» иметь нестандартные WinMainвместо стандартного main.Попутно, с C ++ 0x у Microsoft возникнет проблема с этим, поскольку компилятор должен затем объявить, является ли он автономным или размещенным (при размещении он должен поддерживать стандарт main).

В любом случае, этопричина, по которой g ++ может жаловаться на отсутствие WinMain: это глупая нестандартная функция запуска, которая требуется инструментам Microsoft по умолчанию для программ подсистемы GUI.

Но, как вы можете видеть выше,У g ++ нет проблем со стандартом main даже для программы с подсистемой графического интерфейса.

Так в чем же проблема?

Ну, вы, вероятно, отсутствует a main.И у вас, вероятно, тоже нет (правильного) WinMain!И затем g ++, после поиска main (нет такого) и нестандартного Microsoft WinMain (нет такого), сообщает, что последний отсутствует.

Тестирование с пустым источником:

C:\test> type nul >y.cpp

C:\test> gnuc y.cpp -mwindows
c:/program files/mingw/bin/../lib/gcc/mingw32/4.4.1/../../../libmingw32.a(main.o):main.c:(.text+0xd2): undefined referen
ce to `WinMain@16'
collect2: ld returned 1 exit status

C:\test> _
61 голосов
/ 12 сентября 2012

Подведем итог вышеприведенному посту от Cheers и hth.- Альф, убедитесь, что вы определили main() или WinMain() и g ++ должен делать все правильно.

Моя проблема заключалась в том, что main() был определен внутри пространства имен случайно.

25 голосов
/ 02 августа 2014

Я столкнулся с этой ошибкой при компиляции моего приложения с SDL. Это было вызвано тем, что SDL определил свою собственную основную функцию в SDL_main.h. Чтобы предотвратить определение SDL основной функции, макрос SDL_MAIN_HANDLED должен быть определен до включения заголовка SDL.h.

1 голос
/ 19 июля 2016

Попробуйте сохранить файл .c перед сборкой. Я считаю, что ваш компьютер ссылается на путь к файлу без информации внутри него.

- Подобная проблема возникала при сборке проектов C

...