Visual Studio: Почему линкер требует функцию main если уже определена WinMain (или наоборот)?
В скомпилированной программе всегда есть "главная" функция, с которой начинается выполнение программы.
Краткий ответ: exe и dll это файлы в формате PE(Portable Executable). Адрес точки входа хранится в специальном поле, про который знает загрузчик. Точка входа - это функция, которой передается управление при запуске exe или загрузке dll.
Развернутый ответ: когда исполняемый файл загружается в память компьютера, управление передается на точку входа. Точка входа - это специальная библиотечная функция, которая инициализирует библиотеку времени выполнения (CRT), делает другую подготовительную работу, и вызывает функцию main/WinMain/DllMain. Фактически стандартных точек входа шесть - mainCRTStartup, WinMainCRTStartup, DllMainCRTStartup а также еще три функции с такими же названиями и с приставкой w, которые используются при включенной поддержке юникода: wmainCRTStartup и тд. Это шесть разных функций, из них надо выбрать какую-то одну. Среда Visual Studio выбирает точку входа исходя из настроек проекта.
Функция mainCRTStartup вызывает функцию main, WinMainCRTStartup вызывает функцию WinMain и тд. Представим себе, что программа написана коректно, в ней определяется функция WinMain, однако линкер сообщает: Unresolved external symbol: _main. Это означает, что проект настроен неправильно - выбирается точка входа mainCRTStartup, которая вызывает функцию main. Линкер честно сообщает, что функция main в программе не определяется.
Решение: создавая проект, выбирать правильный тип приложения (Windows Application и функция WinMain или Console Application, main). Позже настройки можно поправить. В 2003 студии это Project->Settings->General->Configuration Type (exe или dll) и Project->Settings->Linker->System->SubSystem (оконное или консольное приложение).
Злой хак: оконное и консольное приложения отличаются не только точкой входа. Фактически можно создать оконное приложение, у которого главной функцией будет main, или консольное приложение с WinMain. Для этого нужно выбрать желаемый тип приложения в настройках проекта и явно указать точку входа во вкладке Linker->Advanced->Entry Point.
26 ноября 2006