Contents

Windows11下由Windows Defender造成的C语言代码编译运行卡顿

本文针对Windows 11 KB5068861 (OS 内部版本 26200.7171 和 26100.7171)版本下编写简单的C语言代码出现运行时间长、IDE出现卡顿等问题提供了一种可能的解决方案。

问题发现

在大一《程序设计基础》这门课考试前夜,学弟突然给我发消息,说他的Code::Blocks出问题了,编译运行任何代码都需要10s左右的时间才能运行出结果。在此引用他的puq(学弟看见后说:是人吗是人吗):

Codeblocks 你是人吗你是人吗你是人吗,你在考程设的前一天给我整死机,最简单的代码你也要运行10秒,你是想杀了我吗你是要杀了我吗[笑脸]这辈子都不会用你了[弱]你是人吗你是人吗你是人吗明天考试怎么办明天考试怎么办 难道要用according 的编译器当我的编译器,拿记事本写代码,出现什么A题居然WA10次的壮举吗[笑脸][笑脸][笑脸]以红温以红温[抱拳]

问题排查

远程连接上他的电脑后,我首先编写了一段简单的Hello World,并按照他说的进行了测试,果然出现了如图所示的问题。 https://gitee.com/michsong/blog-images/raw/master/20251207000119467.png
这很显然是不正常的。那第一步,我们应该干什么呢,当然是重启了!毕竟,重启可以解决99%的问题,你说对吧?
结果不出意外的,这个问题仍未得到解决。看来,这并不是一个偶发性的bug,而是一个由稳定可复现的原因产生的、我们有希望把他排查出来的问题。那么首先,让我们回忆一下,一个C语言的代码,我们是怎么跑起来的:

  1. 预编译。这一步主要的工作就是把代码中的宏等内容直接替换为对应文本。
  2. 编译。由编译器(gcc等)将我们的代码翻译成机器码。
  3. 链接。由链接器将工程中的多个文件按预定的顺序链接起来,最终形成我们的可执行文件。
  4. 运行。

对于一个简单的Hello World代码,我们点击编译并运行,实则相当于执行了下面两个命令:

gcc test.c -o test.exe
.\test.exe

在执行第一条指令后,我们可以发现他马上执行结束,说明这并不是编译的问题。那么真正的运行时间我们怎么看呢?我们把我们的代码改成这样:

#include <stdio.h>
#include <time.h>

int main()
{
    clock_t start = clock();
    
    printf("Hello World!\n");
    
    clock_t end = clock();
    double time_taken = ((double)(end - start)) / CLOCKS_PER_SEC;
    printf("程序执行时间: %f 秒\n", time_taken);
    
    return 0;
}

重新编译运行,可以看到,他输出的执行时间为0.0000000,一个几乎可以忽略不计的时间,说明程序的运行也是正常的。
那么,问题显而易见,就出现在编译成功到运行的这段时间了!
刚才,我们全程使用命令行操作,因此排除掉了IDE调用命令行导致延迟的可能性。而且,在我们不进行编译,第二次运行程序时,可以发现,延迟消失了!那么,我们基本可以断定,对于一个新的可执行文件,操作系统对其进行了一定的操作,导致了我们的延迟。
那究竟是什么操作呢?一个很自然的想法是,杀毒软件(Windows Defender,厂商在系统内置的软件等)对一个未知签名的exe程序进行了检查。同时,与AI的交流也印证了这一点。于是,我开始了如下尝试:

  1. 将文件加入到厂商杀毒软件的信任区。
  2. 将文件加入到Windows Defender ‘病毒与威胁防护’的信任区。
  3. 退出厂商杀毒软件。
  4. 关闭Windows Defender ‘病毒与威胁防护’。
  5. 卸载厂商杀毒软件。

所有的操作均没有解决问题。经过与AI的交流,我们把目光锁定在了Windows Defender ‘应用和浏览器控制’下的 ‘智能应用控制’ 和 ‘基于声誉的保护’两个选项。将其中的选项全部关闭,我们惊奇地发现,问题解决了!于是,这位学弟在上面那条puq下评论:

神!以诞生[强]

而且,据其反馈,当天多位同学遇到了同样的问题,按此法操作,均已得到解决。但是,问题真的解决了吗?

问题复现

为了写这篇博客,我决定在我的电脑上复现这个问题。鉴于学弟告诉我是昨晚更新的,而我的电脑已经好久没有更新过了,所以,我直接打开Dev-C++,运行了如下代码: https://gitee.com/michsong/blog-images/raw/master/20c9f02e36a9ba0f67be0613c2c006fe.jpg 可以看到,我这里的运行时间是完全正常的。或许有眼尖的朋友已经发现了,我的Dev-C++的文字怎么全是乱码啊?别急,这个我们下一篇讲。
于是,我兴致勃勃地向学弟要了他系统的更新日志,结果却发现,他更新的系统版本,和我的是一致的!于是我打开我的Windows Defender,找到上述设置,果然是关闭的。看来,这项设置并非对所有设备均是开放的!
但是,我在测试的过程中,出现了另一个问题:点击“编译并运行”并且在控制台看到编译成功后,Dev-C++出现了长时间的未响应状态,之后才输出结果。与学弟的情况不同的是,我的运行时间显示的是正常的,并不是10s左右的时间!看起来,一定是有程序阻碍了Dev-C++的正常工作——毕竟这么老牌的IDE,几乎不可能出现跑这么简单的一段程序出现崩溃的情况。那么,问题会是什么呢?
于是,我打开了任务管理器,再次重复刚才的操作。结果是,在Dev-C++卡顿的时间,有一个程序的内存占用率出现了显著的提高:Antimalware Service Executable,这项程序展开后,下面是Windows Defender 防病毒服务。看来,问题大概率就是他了!
于是我打开Windows Defender,找到’病毒和威胁防护’设置,关闭了’实时保护’选项。再次运行,一切都正常了。到此,问题解决!

原理分析

以下问题的答案均为与AI讨论生成。

1. 为什么Windows Defender的两项设置,向我们呈现了不同的卡顿结果?

  • 智能应用控制/基于声誉的保护: 这类保护通常发生在**进程创建(Process Creation)**阶段。当你双击运行或由IDE拉起一个exe时,操作系统会暂停该进程的主线程,提取文件特征(Hash)并上传到微软云端进行比对。由于我们写的代码是“全网独一份”且没有数字签名的,云端需要时间分析,或者因无法确认安全而尝试在沙盒中模拟运行。也就是说,这个过程开始前终端已打开,但程序“卡住”不运行,直到云端返回“放行”指令。
  • 实时保护: 这是传统的文件系统实时扫描。当 Dev-C++ 调用 gcc/ld 生成 .exe 文件时,链接器需要将文件写入磁盘。此时 Defender 的文件系统过滤驱动(File System Filter Driver)拦截了写入操作,强制对新生成的文件进行扫描。IDE 此时正在等待链接器进程结束,而链接器被杀毒软件“卡”在写入文件的最后一步,从而导致 IDE 界面出现“未响应”的假死状态。

2. 为什么对于同样的系统环境,呈现不同的默认设置?

  • 微软很可能采用了A/B测试(灰度测试)策略,或者根据系统的初始安装状态来决定。特别是“智能应用控制”,它通常只在全新安装的 Windows 11 上默认开启。如果你的系统是从旧版本升级上来的,为了避免破坏已有软件的兼容性,该功能通常默认关闭。

3. 我的电脑显示无法打开智能应用控制,提示我在不重新安装Windows的情况下无法打开,这是为什么?

  • 这是微软设计的安全基线策略。智能应用控制依赖于一个“纯净”的环境来构建信任链。一旦你关闭它,系统就假设可能已经有未经验证的恶意软件潜入并修改了底层配置。为了确保绝对安全,微软规定必须重置或重新安装 Windows,回到一个可信的初始状态,才能再次开启此功能。

4. 我的电脑打开’基于声誉的保护’后,未出现上述问题,是否可以证明问题实际是由智能应用控制导致的?

  • 是的,基本可以断定。智能应用控制是基于声誉保护的一个更激进、更现代化的超集。
  • 普通的“基于声誉的保护”通常只拦截已知的恶意软件或明显的潜在不受欢迎应用(PUA)。
  • “智能应用控制”则采用“默认拒绝”或“白名单”策略:只要你的程序没有合法的数字签名,且不在微软的云端白名单内,它就会施加极其严格的检查甚至直接拦截。C语言初学者的代码既无签名也无知名度,自然是重点打击对象。

5. 这几项设置的运行原理是什么?怎么影响我的程序运行的?

  • 实时保护:在编译生成阶段,对即将写入磁盘的文件进行全面的检查,导致子进程被迫等待,主进程无响应。
  • 智能应用控制:在运行阶段,检查你的数字签名和云端信誉。如果没有数字签名,它就要联网上传至云端进行判断,导致了10s左右的延迟。

总结

对于Windows 11下出现C语言代码运行时间明显长于预期,可以检查Windows Defender的各项设置,特别是实时保护/智能应用控制部分。当然,对于电脑操作尚不太熟悉的朋友们,仍然不建议把这些功能贸然的关闭!就像网友所说的那样:如果你连360都卸载不掉的话,证明你真的需要360来保护你的电脑。勿谓言之不预也!