了解 MSVC++ 中的"Buffer Security Check /GS"编译器选项
Understanding "Buffer Security Check /GS" compiler option in MSVC++
我最近惊讶地注意到,在msvc++ 2010中使用/GS
(启用缓冲区安全检查)编译在某些情况下似乎对运行时性能有不可忽视的影响。还有其他人有过这样的经历吗?
对于一个大型科学风格的应用程序(一个网格生成库),用/GS-
编译似乎可以在我的测试套件("large")中几个大型基准测试的运行时提高近10%。= 1秒的运行时间)。在msvc++ 2010中,/GS
在所有级别的优化中默认为开启。
我必须承认,我以前从来没有太关注过这个选项,我想要一点澄清,它实际上是做什么的。在线文档似乎广泛讨论字符串缓冲区,但由于我不使用string
或char[]
缓冲区的任何地方,我必须错过的东西。
这段(来自在线文档)似乎表明我所看到的性能下降有点不寻常:
使用的性能权衡必须在应用程序中进行安全检查被制成Visual c++编译器团队专注于表演退化小。在大多数情况下,性能不应该再下降了而不是2%。事实上,经验证明了大多数应用,包括高性能服务器申请,没有注意到任何性能影响。
当然,我可以直接关闭它,以获得更快的代码,但在我这样做之前,我想了解其含义
我有和你一样的经验:/GS-导致运行时改善了约10%。我在我的博客上分享了一些基准测试:Visual c++中缓冲区安全检查的成本
当/GS被启用时(这是vc++发布配置的默认值),似乎任何时候你创建一个c风格的数组作为局部变量,编译器会插入一些额外的指令,以确保堆栈上数组后面的4个字节没有被修改。正如您所注意到的,它是字符数组还是其他类型的数组似乎并不重要。我猜这个编译器选项背后的想法是,任何堆栈缓冲区溢出都可能被黑客利用,无论类型如何。
但是如果你正在开发一个Visual c++应用程序,它不是一个网络服务,并且你正在努力获得最大的性能,比如在游戏,编辑器或基准测试工具中-并且它不太可能成为黑客的目标-那么我建议继续禁用此选项。
/GS添加了一些代码,这些代码试图检测函数期间是否发生了写溢出或类似的堆栈攻击,并在写溢出后停止执行。它旨在寻找的模式是在现实世界的攻击中看到的模式。如果当时使用的是今天的/GS,那么现实世界中的许多安全公告就不会发生。
在这种情况下,写溢出可能发生在结构、数组和各种其他实体上。每个版本的VS都对/GS进行了更改和改进,更多的/GS保护通常是有成本的,尽管在某些情况下,新版本的VS可能已经学会了如何更便宜地做同样的保护。
我建议保持/GS打开,除非你的代码不发送给其他人——通常保护是值得的;您最多可以选择在没有风险和高影响的特定功能中禁用它-就像您可以通过其他方式手动优化程序的最关键部分一样。
Martyn
TrendMicro将标记您的应用程序为可疑的/GS-编译性能
TrendMicro-HouseCall Suspicious_GEN.F47V0828 .
他们似乎也忽略了所有重新评估的请求,认为是假阳性。
- C/C++编译器通常会删除重复的库吗
- 模板-模板参数推导:三个不同的编译器三种不同的行为
- Win32编译器选项和内存分配
- MSVC多行宏编译器错误
- 静态数据成员的问题-修复链接错误会导致编译器错误
- C++,我收到一个无法理解的编译器错误
- 在线编译器中的分段C++没有打印消息
- 如何解决gcc编译器优化导致的centos双编译器设置中的分段错误
- C/C++预处理器是否可以检测一些编译器选项
- 是否有C++编译器选项允许激进地删除所有函数调用,并将参数传递给具有空体的函数
- C++错误C2600:无法定义编译器生成的特殊成员函数(必须首先在类中声明)
- 我需要知道编译器如何在cpp中使用析构函数
- 编译器如何区分std::vector的构造函数
- CLANG 编译器 说:变量"PTR"可能未初始化
- 告诉c++编译器该参数没有别名
- 使用仅使用一次的变量调用的复制构造函数.这可能是通过调用move构造函数进行编译器优化的情况吗
- 为什么所有C++编译器都会崩溃或挂起此代码
- 编译器如何在使用SFINAE的函数和标准函数之间确定两者是否可行
- Visual Studio C++编译器选项:为什么 /O2 定义 /Gs
- 了解 MSVC++ 中的"Buffer Security Check /GS"编译器选项