我注意到MS编译器对像getenv
这样的cstdlib
函数会给出“不推荐使用”的警告。微软已经发明了自己的标准,如_dupenv_s
。
问题1
AFAIK主要的“不安全”的事情是关于可重入性*。既然微软的CRT被标记为“多线程”(/MT
),为什么他们不干脆用可重入的、线程安全的版本取代getenv
呢?是不是每个人都会依赖于这种不安全的行为?
问题2
我用GCC g++ -Wall -Wextra -Weff++ -pedantic foo.cpp
编译了同样的代码,它没有产生任何警告。所以我猜这在POSIX上不是问题?这个问题是如何解决的?(好吧,也许他们只是改变了getenv
的行为,如果能确认这一点就好了)。
*说它“只是关于可重入性”是一种过于概括的说法。当然,我们有像strncpy_s
这样的东西,它可以完全改变签名并处理缓冲区大小。但并没有改变这个问题的核心
发布于 2010-11-27 01:13:09
微软选择这样做让我非常恼火。我知道如何安全地调用所有函数,我不想也不需要这些额外的警告。
只需设置_CRT_SECURE_NO_WARNINGS并使用它即可。这真的很傻。
发布于 2010-11-27 00:52:27
对于getenv
的特定情况,它确实不是可重入的或线程安全的。至于为什么微软不直接替换它,你不能把那个接口变成可重入的(你几乎可以用线程本地存储使它“线程安全”,但它仍然不是可重入的)。
即使您只是完全删除了getenv
,仍然存在environ
变量的问题,它需要一些严重的编译器级别的支持来确保线程安全,因为它只是数据。
实际上,如果您有多个线程,那么使用环境变量而不是“在进程开始之前或进程开始时设置它,并且只从该点开始读取”可能会以失败告终。setenv
和putenv
没有足够丰富的接口来表达“原子地设置这组环境变量”之类的东西,同样,getenv
也没有一种方法来表达“原子地读取这组环境变量”。
在我看来,_dupenv_s
有点傻,因为如果使用它突然让你的代码变得安全,那么使用getenv可能会以一种安全的方式完成。_dupenv_s
解决了在多线程场景中使用环境变量的一小部分问题。
https://stackoverflow.com/questions/4286934
复制相似问题