使用/ ENTRY:main和/ MT运行时库编译为/ SUBSYSTEM:WINDOWS时,应用程序崩溃

时间:2019-04-28 17:34:46

标签: c++ msvcrt

我试图创建一个简单的Windows应用程序,但基于main()入口点,因为我需要在其他平台上对其进行编译。

我发现使用Visual Studio可以执行此操作的特定指令,但是在使用/ MD运行时库编译时似乎可以使用,但是在使用/ MT时会崩溃。

这里是重现崩溃的完整代码,每次都会失败。 ==>只需使用main.cpp文件创建一个空项目并进行设置:Projet->属性-> C / C ++->代码生成->运行时库-> / 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模式的原因。

您有什么建议吗?实际上,我已经为这个问题工作了好几天。...

2 个答案:

答案 0 :(得分:1)

入口点不是from sklearn.feature_extraction.text import TfidfVectorizer vectorizer = TfidfVectorizer() X= test_df.drop('price_status', axis=1) X= vectorizer.fit_transform(X) y= vectorizer.fit_transform(test_df['price_status']) clf = sklearn.svm.SVC(kernel=kernel) clf.fit(X,y) main,它是MS库中将初始化CRT的函数。您的WinMain示例不起作用,因为您绕过了该初始化。 main之所以可行,是因为该初始化发生在WinMain开始执行之前。链接到运行时的DLL版本时,加载DLL时会发生这种初始化。

您应该指定WinMain,或者直接将其保留,然后让链接程序找出正确的子系统。

答案 1 :(得分:0)

将链接器选项放入CONSOLE(更多信息here),仅此而已。 如果您不希望使用控制台,请使用FreeConsole从控制台分离。

另一种简单的解决方案是在Windows上WinMain调用自定义main2,而在其他平台上main调用相同的main2。

#ifdef _WIN32
int __stdcall WinMain(...) { return main2(); }
#else
int main(...) { return main2(); }
#endif