Какие функции выполняет _WinMainCRTStartup?
Это часть серии по крайней мере двух тесно связанных, но разных вопросов. Надеюсь, я поступаю правильно, задавая их отдельно.
Я пытаюсь заставить мое приложение Visual С++ 2008 работать без библиотеки времени выполнения C. Это приложение Win32 GUI без MFC или других причудливых вещей, просто обычный API Windows.
Итак, я установил свойства проекта → Конфигурация → C/С++ → Дополнительно → Опустить имена библиотек по умолчанию в Да (флаг компилятора /Zl
) и перестроен.
Затем компоновщик жалуется на неразрешенный внешний _WinMainCRTStartup
. Достаточно справедливо, я могу сказать компоновщику использовать другую точку входа, скажем MyStartup
. Из того, что я собираю в Интернете, _WinMainCRTStartup
выполняет некоторые операции инициализации, и я, вероятно, хочу, чтобы MyStartup
выполнял подмножество этого.
Итак, мой вопрос: Какие функции выполняет _WinMainCRTStartup
, и какие из них можно опустить, если я не использую CRT?
Если вы хорошо осведомлены об этом, пожалуйста, посмотрите мой другой вопрос. Спасибо!
Кроме того: почему я хочу сделать это в первую очередь?
- В моем приложении явно не используются функции CRT.
- Мне нравятся скудные и средние приложения.
- Это научит меня чему-то новому.
Ответы
Ответ 1
Точка входа CRT делает следующее (этот список не завершен):
- Инициализирует глобальное состояние, необходимое для ЭЛТ. Если это не сделано, вы не можете использовать какие-либо функции или состояние, предоставленные ЭЛТ.
- Инициализирует какое-то глобальное состояние, которое используется компилятором. Проверки времени выполнения, такие как cookie безопасности, используемые /GS, определенно выделяются здесь. Однако вы можете вызвать __ security_init_cookie. Возможно, вам придется добавить другой код для других проверок времени выполнения.
- Вызывает конструкторы на объектах С++. Если вы пишете код на С++, вам может понадобиться подражать этому.
- Извлекает командную строку и запускает информацию, предоставляемую ОС, и передает ее на ваш основной. По умолчанию, никакие параметры не передаются в точку входа программы операционной системой - все они подтверждены ЭЛТ.
Исходный код CRT доступен в Visual Studio, и вы можете пройти через точку входа CRT в отладчике и узнать, что именно он делает.
Ответ 2
Настоящая программа Win32, написанная на C (не С++), вообще не нуждается в инициализации, поэтому вы можете запустить свой проект с помощью WinMainCRTStartup() вместо WinMain (HINSTANCE,...).
Также возможно, но немного сложнее писать консольные программы как настоящие приложения Win32; по умолчанию имя точки входа _mainCRTStartup().
Отключите все дополнительные функции генерации кода, такие как проверки стека, проверки массивов и т.д. Отладка по-прежнему возможна.
Инициализация
Иногда вам нужен первый параметр HINSTANCE. Для Win32 (кроме Win32) он привязан к (HINSTANCE) 0x400000.
Параметр nCmdShow всегда SW_SHOWDEFAULT.
При необходимости загрузите командную строку с помощью GetCommandLine().
Расторжение
Когда ваша программа порождает потоки, например. вызывая GetOpenFileName(), возврат из WinMainCRTStartup() с ключевым словом return приведет к зависанию вашей программы - используйте ExitProcess() > вместо этого.
Предостережения
Вы столкнетесь со значительными проблемами, если:
- с использованием фреймов стека (то есть локальных переменных) размером более 4 Кбайт (для каждой функции)
- с использованием арифметики с плавающей точкой (например, float- > int conversion)
- с использованием 64-разрядных целых чисел на 32-разрядных машинах (операции умножения, бит-сдвиг)
- с использованием С++ new, удалить и статических объектов с конструкторами без нуля-вне всех
- используя стандартные библиотечные функции, например fopen(), printf()
Устранение неполадок
Существует стандартная библиотека C, доступная во всех системах Windows (начиная с Windows 95), MSVCRT.DLL.
Чтобы использовать его, импортируйте свои точки входа, например. используя мой msvcrt-light.lib (google для него). Но есть еще некоторые оговорки, особенно при использовании компиляторов, более новых, чем MSVC6:
- фреймы стека по-прежнему ограничены 4 Кбайтами
- _ftol_sse или _ftol2_sse должен быть перенаправлен на _ftol
- _iob_func должен быть перенаправлен на _iob
Его инициализация запускается во время загрузки. По крайней мере, функции файла будут выполняться без видимых проблем.
Ответ 3
Старый вопрос, но ответы либо неверны, либо сосредоточены на одной конкретной проблеме.
Существует ряд функций C и С++, которые просто не будут доступны в Windows (или большинстве операционных систем, если на то пошло), если программы действительно начались с main/WinMain.
Возьмем этот простой пример:
class my_class
{
public:
my_class() { m_val = 5; }
int my_func(){ return m_val }
private:
int m_val;
}
my_class g_class;
int main(int argc, char **argv)
{
return g_class.my_func();
}
чтобы эта программа функционировала должным образом, конструктор для my_class должен быть вызван до main. Если программа началась точно в главном, для нее потребуется компилятор (обратите внимание: GCC делает это в некоторых случаях), чтобы вставить вызов функции в самом начале main. Вместо этого в большинстве ОС и в большинстве случаев другая функция создает g_class, а затем вызывает main (в Windows это либо mainCRTStartup, либо WinMainCRTStartup; в большинстве других ОС, к которым я привык, используется функция _start).
Иными словами, С++ и даже C должны выполняться до или после работы main.
Как stdin и stdout (std:: cin и std:: cout) можно использовать, как только начнется main?
Как работает atexit?
Стандарт C требует, чтобы стандартная библиотека имела API-интерфейс, подобный POSIX, который в Windows должен быть "установлен" перед main().
В большинстве ОС нет системной кучи; среда выполнения C реализует свою собственную кучу (время выполнения Microsoft C просто обертывает функции Kernel32 Heap).
Даже аргументы, переданные main, argc и argv, должны каким-то образом получить от системы.
Возможно, вы захотите взглянуть на статьи Мэтта Пьетрика (старинного) о реализации его собственной среды выполнения C, чтобы узнать, как это работает с Windows + MSVC (примечание: MinGW и Cygwin реализуют определенные вещи по-разному, но фактически возвращаются к MSVCRT для большинства вещей):
http://msdn.microsoft.com/en-us/library/bb985746.aspx