невизначена посилання на "WinMain @ 16"


110

Коли я намагаюся створити програму за допомогою Eclipse CDT, я отримую наступне:

/mingw/lib/libmingw32.a(main.o):main.c:(.text+0x106): невизначене посилання на `WinMain @ 16

Чому так? І як я можу вирішити це питання?

Відповіді:


184

Розглянемо наступну програму на рівні 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 "^ підсистема"
Підсистема 00000003 (Windows CUI)

C: \ test> _

Це означає, що за замовчуванням лінкер створив виконується консольну підсистему . Значення підсистеми у заголовку файлу повідомляє Windows, які послуги потрібні програмі. У цьому випадку, за допомогою консольної системи, програмі потрібне вікно консолі.

Це також змушує інтерпретатора команд чекати завершення програми.

Тепер давайте побудуємо її за допомогою підсистеми GUI , що просто означає, що програмі не потрібне вікно консолі:

C: \ test> gnuc x.cpp -mwindows

C: \ test> objdump -x a.exe | findstr / i "^ підсистема"
Підсистема 00000002 (графічний інтерфейс Windows)

C: \ test> _

Сподіваємось, це все нормально, хоча -mwindowsпрапор просто напівдокументований.

Будуючи без цього напівдокументованого прапора, потрібно було б конкретніше сказати лінкеру, яку підсистему цінує одне бажання, а деякі бібліотеки імпортування API API потрібно взагалі чітко вказати:

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

C: \ test> objdump -x a.exe | findstr / i "^ підсистема"
Підсистема 00000002 (графічний інтерфейс Windows)

C: \ test> _

Це працювало чудово, за допомогою інструментального ланцюжка GNU.

А як щодо ланцюжка інструментів Microsoft, тобто Visual C ++?

Що ж, створення файлів як консольної підсистеми виконується добре:

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

C: \ test> дампбін / заголовки x.exe | find / i "підсистема" | find / i "Windows"
               3 підсистема (Windows CUI)

C: \ test> _

Однак, якщо побудова інструментальної мережі Microsoft як підсистема GUI не працює за замовчуванням:

C: \ test> msvc x.cpp user32.lib / link / підсистема: windows
x.cpp
LIBCMT.lib (wincrt0.obj): помилка LNK2019: невирішений зовнішній символ _WinMain @ 16 з посиланням на функцію ___tmainCRTStartu
p
x.exe: фатальна помилка LNK1120: 1 невирішені зовнішні

C: \ test> _

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

Немає нічого серйозного, щоб виправити це.

Все, що вам потрібно зробити, - це повідомити лінкеру Microsoft, яку точку входу використовувати, а саме mainCRTStartup, який стандартний виклик main:

C: \ test> msvc x.cpp user32.lib / link / підсистема: windows / entry: mainCRTSзапуск
x.cpp

C: \ test> дампбін / заголовки x.exe | find / i "підсистема" | find / i "Windows"
               2 підсистема (інтерфейс Windows)

C: \ test> _

Без проблем, але дуже нудно. І настільки прихованим і прихованим, що більшість програмістів Windows, які здебільшого використовують лише нестандартні інструменти Microsoft за замовчуванням, про це навіть не знають, і помилково думають, що програма підсистеми Windows GUI "повинна" мати нестандартну WinMainзамість стандартної main. Мимоволі з C ++ 0x у Microsoft виникне проблема з цим, оскільки компілятор повинен рекламувати, незалежно від того, чи він є вільним, так і розміщеним (коли він розміщений, він повинен підтримувати стандарт main).

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

Але, як ви бачите вище, g ++ не має проблем із стандартом mainнавіть для програми підсистеми GUI.

То в чому може бути проблема?

Ну, ви, ймовірно , що не вистачаєmain . І у вас, мабуть, немає (належного) WinMain! А потім g ++ після пошуку main(немає такого) та нестандартного WinMain(немає такого) Microsoft повідомляє, що останнього немає.

Тестування з порожнім джерелом:

C: \ test> введіть nul> y.cpp

C: \ test> gnuc y.cpp -mwindows
c: / програмні файли / mingw / bin /../ lib / gcc / mingw32 / 4.4.1 /../../../ libmingw32.a (main.o): main.c :(. текст + 0xd2 ): невизначене посилання
Це до `WinMain @ 16 '
collection2: ld повернув 1 статус виходу

C: \ test> _

3
@Alf P. Steinbach. Дякую за гарну відповідь. Що стосується All you have to do is to tell Microsoft's linker which entry point to use, namely mainCRTStartup, which calls standard main. Чи є спосіб це зробити, Eclipse CDTоскільки я не використовую командний рядок. Спасибі
Простота

1
@ user588855: оскільки ви використовуєте g ++, це (ймовірно) не стосується вас. Застосовується лише частина в кінці (ймовірно). Тобто визначте a mainабо a WinMain, або переконайтеся, що відповідний файл включений у проект. Ура,
ура та хт. - Альф

@Alf P. Steinbach. Що ви маєте на увазі, визначаючи mainчи winmain? Спасибі
Простота

1
Я щойно створив файл з назвою main.cpp, який мав код: int main () {}
дійсно

3
Мені було б добре, якби кожен судівник міг би пояснити свій голос. Для інших читачів, можливо, таке саме помилкове уявлення (що б воно не було), і тоді ми могли б це зрозуміти. Кожна людина отримала б користь, замість того, щоб когось вводити в оману. Отож, поясніть, будь ласка, свою заяву. Дякую.
ура та хт. - Альф

68

Узагальнити вищезазначений пост Cheers and hth. - Альф, переконайся, що ти маєш main()або WinMain()визначив, і g ++ має робити правильно.

Моя проблема полягала в тому, що вона main()була визначена всередині простору імен випадково.


Просто зрозумів щось важливе у всьому цьому. У моєму випадку він не знаходив main (), оскільки я не оголошував жодних аргументів (argc, argv). Після додавання він знайшов головним. Також характер того, як це працює, означає, що mingw намагається допомогти, надаючи власне основне, яке в свою чергу викликає WinMain. Програми GUI матимуть лише WinMain, а для туди використовується головна заглушка в mingw. Якщо у вас є головний, то він використовує це замість цього.
Джефф Муїр

extern "C" int main (void)
вирішив

33

Я зіткнувся з цією помилкою під час компіляції моєї програми з SDL. Це було викликано SDL, визначаючи його основну функцію в SDL_main.h. Щоб запобігти визначенню SDL основної функції, перед включенням заголовка SDL.h слід визначити макрос SDL_MAIN_HANDLED.


Чудова відповідь! +1
Мохаммед Канан

Дуже дякую! Ця команда працює: gcc main.c -I "E: \ Libs \ SDL2-devel-2.0.12-mingw \ SDL2-2.0.12 \ i686-w64-mingw32 \ include" -I "E: \ Libs \ SDL2_ttf- devel-2.0.15-mingw \ SDL2_ttf-2.0.15 \ i686-w64-mingw32 \ включають "-L" E: \ Libs \ SDL2-devel-2.0.12-mingw \ SDL2-2.0.12 \ i686-w64- mingw32 \ lib "-L" E: \ Libs \ SDL2_ttf-devel-2.0.15-mingw \ SDL2_ttf-2.0.15 \ i686-w64-mingw32 \ lib "-lSDL2 -lSDL2main -lSDL2_ttf -o app.exe
8Observer8

5

Спробуйте зберегти свій .c файл перед створенням. Я вважаю, що ваш комп'ютер посилається на шлях до файлу, в якому немає інформації.

- Має подібне питання під час створення проектів на С


Це фактично вирішило мою проблему, і я залишаю цей коментар, щоб допомогти йому привернути більше уваги.
Девід Чен

0

Перевірте, чи всі файли включені у ваш проект:

У мене виникла така ж помилка після оновлення cLion. Після годин майстерності я помітив, що один із моїх файлів не був включений у ціль проекту. Після того як я знову додав його до активного проекту, я перестав отримувати невизначене посилання на winmain16 і код скомпільований.

Редагувати: Також варто перевірити налаштування збірки у вашому IDE.

(Не впевнений, що ця помилка пов'язана з нещодавним оновленням IDE - може бути причинним або просто співвіднесеним. Не соромтесь коментувати будь-яке розуміння цього фактора!)

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.