windows 警告 C4996:与 POSIX 上的 GCC 相比,此函数或变量可能不安全

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/4286934/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-15 15:41:04  来源:igfitidea点击:

Warning C4996: This function or variable may be unsafe -- compared to GCC on POSIX

c++windowsvisual-c++gcc

提问by kizzx2

I notice that MS compilers give "deprecated" warnings for cstdlibfunctions like getenv. MS has invented its own standard such as _dupenv_s.

我注意到,MS编译器会给出“弃用”警告,cstdlib类似的功能getenv。MS 发明了自己的标准,例如_dupenv_s.

Question 1

问题 1

AFAIK the main "unsafe" thing is about reentrancy *. Since MS's CRT is marked as "multi-threaded" (/MT), why don't they just replace getenvwith the reentrant, thread-safe version? Is it like anybody would depend on the unsafe behavior?

AFAIK 主要的“不安全”的事情是关于可重入性 *。既然 MS 的 CRT 被标记为“多线程”(/MT),他们为什么不直接替换getenv为可重入的线程安全版本?是否有人会依赖于不安全的行为?

Question 2

问题2

I compiled the same code with GCC g++ -Wall -Wextra -Weff++ -pedantic foo.cppand it doesn't yield any warnings. So I guess this is not a problem on POSIX? How is this solved? (OK maybe they just changed the behavior of getenv, would be nice to have this confirmed).

我用 GCC 编译了相同的代码,g++ -Wall -Wextra -Weff++ -pedantic foo.cpp它没有产生任何警告。所以我想这在 POSIX 上不是问题?这是如何解决的?(好吧,也许他们只是改变了 的行为getenv,如果能确认这一点就好了)。

* It's an over-generalization to say that its' only about reentrancy. Of course we have things like strncpy_swhich changes the signature completely and deals with buffer size. But doesn't change the core of this question

*说它只是关于可重入性是一种过度概括。当然,我们有一些事情strncpy_s可以完全改变签名并处理缓冲区大小。但并没有改变这个问题的核心

回答by Ben Karel

  1. In a sane world, the answer would be "of course not, that would be stupid!" In this world, though, it seems there is no end of gut-wrenchingly poorly thought out undocumented behavior upon which people will stoop to depending upon. Raymond Chenhas a great collection of such anecdotes (anecdon'ts?) in his blog. Such as the hideous practice of using a bug in the loader to share thread-local variables between an exe and a DLL. When you have as many customers as Microsoft does, the only safe choice is to never even risk breaking backwards compatibility.

  2. The difference in warnings is because cl.exeis going out of its way to highlight a potential security problem, and g++isn't. getenvand putsand friends are all still broken under POSIX, but (at least for getenv) there isn't a more secure alternative in the standard library. And, unlike Microsoft, the GNU folks probably see a standard library call with potential security problems as a lesser evil than a more secure but platform-specific library call.

  1. 在一个理智的世界里,答案是“当然不会,那太愚蠢了!” 然而,在这个世界上,人们会屈服于依赖的令人痛苦的深思熟虑的无证行为似乎永无止境。Raymond Chen在他的博客中收集了大量这样的轶事(轶事?)。例如使用加载程序中的错误在 exe 和 DLL 之间共享线程局部变量的可怕做法。当您拥有与 Microsoft 一样多的客户时,唯一安全的选择就是永远不要冒险破坏向后兼容性。

  2. 警告的不同之处在于cl.exe,它会特意强调潜在的安全问题,而g++事实并非如此。getenvputs和朋友们在 POSIX 下仍然被破坏,但是(至少对于getenv)标准库中没有更安全的替代方案。而且,与 Microsoft 不同的是,GNU 人员可能将具有潜在安全问题的标准库调用视为比更安全但特定于平台的库调用的危害较小。

回答by Joshua

It annoys the heck outta me that Microsoft chose to do this. I know how to call all the functions safely, I don't want or need these extra warnings.

微软选择这样做让我很恼火。我知道如何安全地调用所有函数,我不想要或不需要这些额外的警告。

Just set _CRT_SECURE_NO_WARNINGS and be done with it. It's really that silly.

只需设置 _CRT_SECURE_NO_WARNINGS 并完成它。真的是那么傻。

回答by Logan Capaldo

For the specific case of getenv, it is indeed not reentrant or thread safe. As for why Microsoft doesn't just replace it, you can't take that interface and make it reentrant (you can almost make it "thread safe" with thread local storage, but it would still not be reentrant).

对于 的特定情况getenv,它确实不是可重入的或线程安全的。至于为什么微软不只是替换它,你不能拿那个接口让它可重入(你几乎可以用线程本地存储使它“线程安全”,但它仍然不会是可重入的)。

Even if you just took getenvaway altogether, there is still the problem that you have the environvariable which would require some serious compiler level support to make thread safe, since it is just data.

即使您完全拿走getenv,仍然存在一个问题,即您拥有environ需要一些严格的编译器级别支持才能使线程安全的变量,因为它只是数据。

Really, using environment variables for anything other than "setting it up before the process starts or at process start, and only reading from it from that point on" is going to probably end in tears if you have more than one thread. setenvand putenvdon't have a rich enough interface to express something like "set this set of environment variables atomically" and likewise getenvdoesn't have a way to express "read this set of environment variables atomically".

真的,如果您有多个线程,除了“在进程开始之前或在进程开始时设置它,并且只从那一刻开始读取它”之外,将环境变量用于任何其他事情可能会以流泪结束。setenv并且putenv没有足够丰富的接口来表达诸如“以原子方式设置这组环境变量”之类的内容,同样getenv也没有办法表达“以原子方式读取这组环境变量”。

_dupenv_sis somewhat silly in my opinion, because if using that suddenly makes your code safe, it could probably done in a safe way with getenv. _dupenv_ssolves a tiny subset of the problems with using environment variables in a multithreaded scenario.

_dupenv_s在我看来有点愚蠢,因为如果使用它突然使您的代码安全,它可能可以通过 getenv 以安全的方式完成。_dupenv_s解决了在多线程场景中使用环境变量的一小部分问题。