【问题标题】:How can getenv() be thread-safe?getenv() 如何是线程安全的?
【发布时间】:2015-05-27 08:06:20
【问题描述】:

我想使用getenv() 函数。

现在我从某人那里得到一个评论,如果多个线程正在调用这个函数,这将不是线程安全的。但是,如果我查看此函数的 information page,它会指出:

只要环境不变,并发调用这个函数是安全的。

我理解静态数据块的概念,函数返回一个指向它的指针。我知道块的内容会随着时间的推移而改变,通过多次调用函数,就像参考页面状态一样。

如果一个线程正在调用

getenv("myEnvVar1")

另一个人在打电话

getenv("myEnvVar2")

返回的指针指向的地方会使用相同的内存块吗?我应该如何理解“并发调用这个函数是安全的”这一事实?

【问题讨论】:

  • 我认为这意味着只要您不调用setenv或以其他方式修改环境就可以了。

标签: c++


【解决方案1】:

getenv 返回一个指向 ACTUAL 环境内容的指针——因此该进程有一个字符串数组,其中包含环境变量,而您返回的不是副本,而是指向它的 ACTUAL 指针。

请注意,char *p = getenv("foo"); ... setenv("foo", "new value"); ... use p 也是未定义的,因为 p 指向的字符串现在很可能已经发生了变化[并且没有以明确的方式]

【讨论】:

    【解决方案2】:

    不是。

    函数getenv 是C 标准库的一部分,因此它的行为由一组C 标准指定。

    POSIX.1-2017(遵循 ISO C 标准)规定:

    • 返回的字符串指针可能无效,或者字符串内容可能被后续调用getenv()覆盖, setenv()unsetenv() 或(如果支持)putenv(),但它们不应 受到对本卷中任何其他函数的调用的影响 POSIX.1-2017。

    • 如果调用线程终止,返回的字符串指针也可能无效。

    • getenv() 函数不必是线程安全的。

    ISO C11(POSIX 遵循),说:

    环境名称集和更改方法 环境列表是实现定义的。 getenv 函数 不需要避免与修改的其他执行线程的数据竞争 环境列表。

    您不能确定getenv 本身在搜索时不会修改环境(我想不出为什么会,但这样做不会违反标准)。如果您想确定您使用的 getenv 版本是线程安全的实现,您必须查阅您的实现文档以确认它是。

    【讨论】:

    • 不。你提到了错误的规则。它应该是“指向的字符串不应被程序修改,但可能会被随后对getenv 函数的调用覆盖”。但是,C++ 自 C++11 起就有an explicit requirement of std::getenv disallowing this across different threads。一旦任何定义明确的操作(例如通过返回指向每个线程副本的指针)可以证明结果不被其他线程共享,则仍然允许实现使同一线程中的指针无效。
    • @FrankHB"指向的字符串不应被程序修改,但可能会被后续调用 getenv 函数覆盖" 任何参考? “你提到了错误的规则。”?哪一个引用了错误的规则?
    猜你喜欢
    • 1970-01-01
    • 2011-02-26
    • 2019-10-06
    • 1970-01-01
    • 2014-08-10
    • 2011-08-13
    • 2015-12-01
    • 1970-01-01
    • 2014-03-10
    相关资源
    最近更新 更多