使用 /ENTRY:main 和 /MT 运行时库编译为 /SUBSYSTEM:WINDOWS 时应用程序崩溃
Application crashes when compiled as /SUBSYSTEM:WINDOWS with /ENTRY:main and /MT runtime library
我正在尝试创建一个简单的 windows 应用程序,但基于 main() 入口点,因为我需要在其他平台上编译它。
我找到了使用 visual studio 执行此操作的特定指令,但它似乎在使用 /MD 运行时库编译时有效,但在使用 /MT 时崩溃。
这是重现崩溃的完整代码,每次都失败。
==> 只需使用 main.cpp 文件创建一个空项目并设置:Projet -> Properties -> C/C++ -> Code Generation -> Runtime Library -> /MT
#pragma comment(linker, "/SUBSYSTEM:WINDOWS")
#pragma comment(linker, "/ENTRY:main")
#pragma comment(linker, "/INCLUDE:mainCRTStartup")
int main(int argc, char** argv)
{
int* a = new int;
delete a;
return 0;
}
这会导致以下异常:
ntdll.dll!RtlpWaitOnCriticalSection() Inconnu
ntdll.dll!RtlpEnterCriticalSectionContended() Inconnu
ntdll.dll!RtlEnterCriticalSection() Inconnu
Application.exe!__acrt_lock(__acrt_lock_id _Lock) Ligne 55 C++
Application.exe!heap_alloc_dbg_internal(const unsigned __int64 size, const int block_use, const char * const file_name, const int line_number) Ligne 309 C++
Application.exe!heap_alloc_dbg(const unsigned __int64 size, const int block_use, const char * const file_name, const int line_number) Ligne 450 C++
Application.exe!_malloc_dbg(unsigned __int64 size, int block_use, const char * file_name, int line_number) Ligne 496 C++
Application.exe!malloc(unsigned __int64 size) Ligne 27 C++
[Code externe]
Application.exe!main(int argc, char * * argv) Ligne 9 C++
[Code externe]
但是如果我使用 WinMain 入口点,它不会失败:
#pragma comment(linker, "/SUBSYSTEM:WINDOWS")
int main(int argc, char** argv)
{
int* a = new int;
delete a;
return 0;
}
INT WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR lpCmdLine, INT nCmdShow)
{
return main(1, reinterpret_cast<char**>(&lpCmdLine));
}
我想在没有 MSVCRT 外部依赖的情况下进行编译,这就是我设置 /MT 模式的原因。
你有什么建议吗?我实际上已经在这个问题上工作了好几天....
将链接器选项设置为 CONSOLE(更多信息 here),仅此而已。
如果您不想要控制台,请使用 FreeConsole.
将其分离
另一个简单的解决方案是 WinMain
在 Windows 上调用自定义 main2
并在其他平台上让 main 调用相同的 main2。
#ifdef _WIN32
int __stdcall WinMain(...) { return main2(); }
#else
int main(...) { return main2(); }
#endif
入口点不是 main
或 WinMain
,它是 MS 库中将初始化 CRT 的函数。您 main
示例不起作用,因为您绕过了该初始化。 WinMain
示例之所以有效,是因为此初始化发生在 WinMain
开始执行之前。当链接到运行时的 DLL 版本时,此初始化会在加载 DLL 时发生。
您应该指定 /SUBSYSTEM:CONSOLE
,或者干脆不指定,让链接器找出正确的子系统。
我正在尝试创建一个简单的 windows 应用程序,但基于 main() 入口点,因为我需要在其他平台上编译它。
我找到了使用 visual studio 执行此操作的特定指令,但它似乎在使用 /MD 运行时库编译时有效,但在使用 /MT 时崩溃。
这是重现崩溃的完整代码,每次都失败。 ==> 只需使用 main.cpp 文件创建一个空项目并设置:Projet -> Properties -> C/C++ -> Code Generation -> Runtime Library -> /MT
#pragma comment(linker, "/SUBSYSTEM:WINDOWS")
#pragma comment(linker, "/ENTRY:main")
#pragma comment(linker, "/INCLUDE:mainCRTStartup")
int main(int argc, char** argv)
{
int* a = new int;
delete a;
return 0;
}
这会导致以下异常:
ntdll.dll!RtlpWaitOnCriticalSection() Inconnu
ntdll.dll!RtlpEnterCriticalSectionContended() Inconnu
ntdll.dll!RtlEnterCriticalSection() Inconnu
Application.exe!__acrt_lock(__acrt_lock_id _Lock) Ligne 55 C++
Application.exe!heap_alloc_dbg_internal(const unsigned __int64 size, const int block_use, const char * const file_name, const int line_number) Ligne 309 C++
Application.exe!heap_alloc_dbg(const unsigned __int64 size, const int block_use, const char * const file_name, const int line_number) Ligne 450 C++
Application.exe!_malloc_dbg(unsigned __int64 size, int block_use, const char * file_name, int line_number) Ligne 496 C++
Application.exe!malloc(unsigned __int64 size) Ligne 27 C++
[Code externe]
Application.exe!main(int argc, char * * argv) Ligne 9 C++
[Code externe]
但是如果我使用 WinMain 入口点,它不会失败:
#pragma comment(linker, "/SUBSYSTEM:WINDOWS")
int main(int argc, char** argv)
{
int* a = new int;
delete a;
return 0;
}
INT WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR lpCmdLine, INT nCmdShow)
{
return main(1, reinterpret_cast<char**>(&lpCmdLine));
}
我想在没有 MSVCRT 外部依赖的情况下进行编译,这就是我设置 /MT 模式的原因。
你有什么建议吗?我实际上已经在这个问题上工作了好几天....
将链接器选项设置为 CONSOLE(更多信息 here),仅此而已。 如果您不想要控制台,请使用 FreeConsole.
将其分离另一个简单的解决方案是 WinMain
在 Windows 上调用自定义 main2
并在其他平台上让 main 调用相同的 main2。
#ifdef _WIN32
int __stdcall WinMain(...) { return main2(); }
#else
int main(...) { return main2(); }
#endif
入口点不是 main
或 WinMain
,它是 MS 库中将初始化 CRT 的函数。您 main
示例不起作用,因为您绕过了该初始化。 WinMain
示例之所以有效,是因为此初始化发生在 WinMain
开始执行之前。当链接到运行时的 DLL 版本时,此初始化会在加载 DLL 时发生。
您应该指定 /SUBSYSTEM:CONSOLE
,或者干脆不指定,让链接器找出正确的子系统。