如何完全禁用CRT

cvxl0en2  于 2023-03-12  发布在  其他
关注(0)|答案(2)|浏览(163)

如何完全禁用Visual Studio提供的所有运行时错误消息?
我的意思是,根本没有把它们包含在我的应用程序中。
我自己在向量化异常处理程序中处理错误,我不想一直调用_CrtSetReportMode。
谢谢!

syqv5f0l

syqv5f0l1#

〉〉如何完全禁用CRT

就我而言,一般情况下,您无法完全禁用CRT:
1,入口点(从控制台获取输入)
2、提供C和C++中常用的函数
如果您希望在不使用C运行时库(CRT)的情况下编译应用,我建议您尝试使用/MT/NODEFAULTLIB链接器选项,并将Linker -> Advanced -> Entry Point处的入口点重新定义为代码中定义的函数。

eaf3rand

eaf3rand2#

老问题了,管他呢。
“简短”的回答,这篇帖子:
https://hero.handmade.network/forums/code-discussion/t/94-guide_-_how_to_avoid_c_c++_runtime_on_windows
长回答:

  • 我不喜欢帖子中的一些事情(上面的链接),但我喜欢这个视频(他看视频中的链接):*

观看此视频(3小时长,但值得,还没有看完整个视频,但即使他说他已经完成了删除CRT的东西,他会谈论潜在的问题,你可以找到,或先阅读此答案:D):https://www.youtube.com/watch?v=sE4tUVaxiV0

  • 我将给予Visual Studio编译器的步骤,对于其他编译器,我不知道它是如何工作的。*
  • 另外,我是巴西人,所以如果命令名等不完全匹配,就去最接近的。*

首先,让我们对配置进行所有需要进行的更改:

  • 您需要根据需要更改项目配置中的子系统,如果是Windows,则为:
  • 链接器-〉系统-〉子系统=〉Windows(/SUBSYSTEM:WINDOWS)
  • 我不知道Linux是怎么回事 *
  • 设置为不包含其他库:
  • 链接器-〉条目-〉忽略所有默认库=〉是(/NODEFAULTLIB)

您需要的所有其他库都可以使用
#pragma comment(lib, "lib name here using the quotation marks"),或者您可以使用 “Ignore default libs” 上面的字段。

  • 删除Visual Studio的所有检查项:我不知道你是否需要删除所有这些,但如果你像我一样,因为你删除CRT,你可能不希望任何类型的检查或什么的。无论如何,这里是我的事情的完整列表:
  • C/C++ -〉代码生成-〉启用c++异常=〉
  • C/C++ -〉代码生成-〉基本运行时验证=〉默认值
  • C/C++ -〉代码生成-〉安全检查=〉/GS-
  • C/C++ -〉代码生成-〉启用浮点异常=〉否(/fp:except-)

第二,你的切入点;注意它不是WinMain(...)它是WinMainCRTStartup(),如下所示:

// No parameters
DWORD WINAPI WinMainCRTStartup()  
{  
    ...  
}

WINAPI只是__stdcall的宏。
从技术上讲,它的定义是使用DWORD,但我通常使用int
文档说你应该使用ExitProcess(_return value_);来退出代码,我自己就是这么做的,如果你这么做了,你甚至不需要使用return ~;虽然有人会说这是很好的练习,但我认为这是无用的。
最后一件事:
现在的编译器喜欢使用CRT,而我讨厌CRT。所以如果你试图编译代码,代码中没有任何东西,所有的东西都可以工作,但是你可能会遇到更多的东西的问题:
你需要定义你自己的memset()和定义一个_fltusedmemesetmemset,编译器在你创建大数组的时候使用它,当你使用float的时候使用_fltused(浮点数,不知道)。
老实说,只是复制这个文件我做的,而且,Visual Studio不喜欢,如果你这样做的头文件,所以这样做的.c文件mine_msvc.c例如:

extern "C"
{
    // Don't actually know if you need the value, since looks like it works even without it, I myself leave it with the value.
    int _fltused = 0x9875;

#pragma warning( push )
#pragma warning( disable : 28251 )
#pragma warning( disable : 6001 )

#pragma function(memset)
    void* __cdecl memset(void* dest, int val, size_t tam)
    {
        char* retDest = (char*)dest;

        while (tam--)
            *retDest++ = (char)val;

        return retDest;
    }
}

#pragma warning( pop )

另外,记住基本的C++内容,你不能在每个地方都使用它,因为有多个定义,我自己在我的库中使用它,我有一个EXTERN宏,但是你可以做一个头文件:

extern "C" 
{
    extern int _ftlused;

    void* __cdecl memset(void* dest, int val, size_t tam);
}

我会说这就是全部(看最后一段),我用来检查是否真的有更多的东西将使用“Dependencies.exe”,但对我来说,至少它只是变得不太可靠,所以你可以做的是使用IDA或Ghidra,我不知道如何使用Ghidra,我只是使用IDA的免费版本。
至少在左侧面板的“IDA”中,您可以看到函数,所有名为sub_~number~的内容都是您的,您甚至可以使用您的汇编知识检查函数,有些其他内容可能不会像这样调用,例如,在我的示例中,我有一个名为fn的Windows钩子和一个名为StartAddress的线程,加上实际的start。如果你看到很多函数有奇怪的名字,有些东西在你没有问的情况下就被链接了。
我个人不太清楚可执行文件是如何组成的,但是在“IDA”中,您可以查看文件的末尾,或者搜索这样的位置

;
; Import names for "dll name"
;

并查看代码使用的额外函数,大多数(如果不是全部)都是Windows强制函数或您使用的API函数。
最后,如果你使用它,* 当然你不能使用CRT中的任何东西 *,但你不能使用newdelete,你仍然可以使用STL,因为它们是模板,我个人不喜欢它们,也不使用它们;你不能使用C++错误处理,因为它是CRT的一部分。
在我写这篇文章的时候,我仍然没有遇到任何问题,使用这些选项,但你可以有额外的问题,如堆栈大小,线程堆栈大小等。关于这一点,阅读链接或观看视频,因为例如,对于堆栈大小检查,你可以实现自己的__chkstk,但我不知道如何做到这一点+,因为现在1 MB是什么,你可以只使用编译器选项来请求自启动以来的1 MB;同样,只要阅读第一个链接。

相关问题