Вопрос или проблема
Когда я пытаюсь собрать программу с помощью Eclipse CDT, я получаю следующее сообщение:
/mingw/lib/libmingw32.a(main.o):main.c:(.text+0x106):
undefined reference to `WinMain@16
Почему это происходит? И как я могу решить эту проблему?
Эта ошибка возникает, когда linker не может найти функцию WinMain, поэтому, вероятно, она отсутствует. В вашем случае скорее всего отсутствует и main. Рассмотрим следующую программу на уровне Windows API:
#define NOMINMAX
#include <windows.h>
int main()
{
MessageBox( 0, "Blah blah...", "My Windows app!", MB_SETFOREGROUND );
}
Теперь давайте соберем ее с помощью GNU toolchain (т.е. g++), без специальных опций. Здесь gnuc – это просто пакетный файл, который я использую для этого. Он лишь предоставляет опции, чтобы сделать g++ более стандартным:
C:\test> gnuc x.cpp
C:\test> objdump -x a.exe | findstr /i "^subsystem"
Subsystem 00000003 (Windows CUI)
C:\test> _
Это означает, что linker по умолчанию сгенерировал исполняемый файл с консольным подсистемой. Значение подсистемы в заголовке файла сообщает Windows, какие службы требует программа. В данном случае, для консольной системы, программа требует консольное окно. Это также заставляет командный интерпретатор ожидать завершения программы. Теперь давайте соберем ее с подсистемой GUI, что просто означает, что программе не требуется консольное окно:
C:\test> gnuc x.cpp -mwindows
C:\test> objdump -x a.exe | findstr /i "^subsystem"
Subsystem 00000002 (Windows GUI)
C:\test> _
Надеюсь, это нормально, хотя флаг -mwindows просто полудокументирован. Собирая без этого полудокументированного флага, вам нужно более конкретно указать linker, какое значение подсистемы вы желаете, и некоторые библиотеки импорта 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 toolchain. Но что насчет Microsoft toolchain, т.е. 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> _
Технически это происходит потому, что linker от Microsoft по умолчанию не соответствует стандарту для GUI подсистемы. По умолчанию, когда подсистема GUI, linker Microsoft использует точку входа в библиотеке времени выполнения, функцию, где начинается выполнение машинного кода, называемую winMainCRTStartup, которая вызывает нестандартную WinMain вместо стандартной main. Никакой проблемы это не представляет для исправления. Вам просто нужно сообщить linker от 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 по умолчанию, даже не знают об этом и ошибочно полагают, что программа GUI подсистемы "должна" иметь нестандартную WinMain вместо стандартной main. Кстати, с C++0x у Microsoft будет проблема с этим, поскольку компилятор должен будет объявить, является ли он свободным или хостируемым (когда он хостируемый, он должен поддерживать стандартную main). В любом случае, вот причина, по которой g++ может жаловаться на отсутствие WinMain: это глупая нестандартная функция запуска, требуемая инструментами Microsoft по умолчанию для программ с GUI подсистемами. Но, как вы видите выше, g++ не имеет проблем со стандартной main даже для программы с GUI подсистемой. Так в чем же может быть проблема? Скорее всего, вам не хватает main. И у вас, вероятно, тоже нет (правильной) WinMain! И, следовательно, g++, после того как он искал main (не найден), и для нестандартной WinMain от Microsoft (не найден), сообщает об отсутствии последней. Тестирование с пустым исходным кодом:
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> _
В заключение вышеуказанного сообщения от Cheers and hth. – Альф, убедитесь, что у вас определены main() или WinMain(), и g++ должен сделать все правильно.
Моя проблема заключалась в том, что main() была случайно определена внутри пространства имен.
Я сталкивался с этой ошибкой, компилируя свое приложение с SDL. Это было вызвано тем, что SDL определяет свою собственную функцию main в SDL_main.h. Чтобы предотвратить определение функции main в SDL, необходимо определить макрос SDL_MAIN_HANDLED перед включением заголовка SDL.h.
Попробуйте сохранить свой файл .c перед сборкой. Я считаю, что ваш компьютер ссылается на путь к файлу, который не содержит информации.
Моя ситуация заключалась в том, что у меня не было функции main.
Проверьте, что все файлы включены в ваш проект:
У меня появилась такая же ошибка после обновления cLion. После нескольких часов возни, я заметил, что один из моих файлов не был включен в целевой проект. После того, как я добавил его обратно в активный проект, я перестал получать неопределенную ссылку на winmain16, и код скомпилировался.
Редактирование: также стоит проверить настройки сборки в вашем IDE.
(Не уверен, связано ли это с тем, что я недавно обновил IDE – это может быть причиной или просто корреляцией. Не стесняйтесь оставлять комментарии с любыми соображениями на этот счет!)
У меня была та же проблема. Чтобы исправить это, я нажал "Сохранить", чтобы сохранить свой файл .c перед сборкой. Я считаю, что мой компьютер ссылался на путь к файлу, который не содержит информации.
Ответ или решение
Ошибка "undefined reference to WinMain@16'" возникает, когда компилятор не может найти точку входа для Windows-приложения. В Windows-приложениях, скомпилированных с использованием определённых инструментов, для GUI-приложений требуется функция
WinMainвместо стандартной функции
main`. Причиной этой ошибки может быть отсутствие необходимой функции или неправильные настройки проекта.
Причины возникновения ошибки и решения:
-
Отсутствие функции
main
илиWinMain
:
Убедитесь, что у вас определена хотя бы одна из этих функций. Для Windows-приложения обычно требуетсяWinMain
, а для консольных приложений —main
.// Пример WinMain #include <windows.h> int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nShowCmd) { MessageBox(0, "Hello, Windows!", "Sample", MB_OK); return 0; }
Если же ваше приложение должно быть консольным, убедитесь, что используется стандартная функция
main
и добавьте-mwindows
флаг для компоновщика:#include <stdio.h> int main() { printf("Hello, Console!\n"); return 0; }
-
Неправильная настройка компоновщика:
Возможно, ваш проект настроен неправильно, например, как Windows GUI без определенияWinMain
. Проверьте настройки вашего компилятора или IDE, чтобы убедиться, что у вас установлены правильные параметры компоновщика. -
Программные библиотеки, такие как SDL:
Если используете библиотеки, такие как SDL, они могут определять свою собственнуюmain
. В этом случае нужно использовать директивуSDL_MAIN_HANDLED
перед включением заголовка SDL:#define SDL_MAIN_HANDLED #include <SDL.h>
-
Убедитесь, что файл сохранён и все необходимые файлы проекта добавлены:
Проверьте, что все изменения, которые вы сделали, были сохранены в файле, и что все файлы, задействованные в проекте, включены в его сборку. Иногда, особенно после обновлений IDE, некоторые файлы могут быть исключены из сборки проекта. - Проверка файлов конфигурации и целевых платформ:
Убедитесь, что вы используете правильные настройки сборки (например, x86 или x64) в соответствии с вашей операционной системой и используемыми библиотеками.
Убедитесь, что выполняете обязательно корректные шаги на этапах компиляции и привязки, и тогда ошибка "undefined reference to `WinMain@16’" должна исчезнуть. Если проблема сохраняется, попробуйте создать новый проект с минимальным кодом, чтобы изолировать проблему.