当前位置: 首页 > 面试题库 >

关于putenv()和setenv()的问题

乐正浩博
2023-03-14
问题内容

我一直在思考环境变量,并有一些问题/观察。

  • putenv(char *string);

此呼叫似乎存在致命缺陷。因为它不会复制传递的字符串,所以您不能使用本地调用它,并且不能保证分配给堆的字符串不会被覆盖或意外删除。此外(尽管我尚未测试过),因为环境变量的一种用法是将值传递给孩子的环境,如果孩子调用其中一个exec*()功能,这似乎毫无用处。我说错了吗?

  • Linux手册页指示glibc 2.0-2.1.1放弃了上述行为,并开始复制字符串,但这导致内存泄漏,该问题已在glibc 2.1.2中修复。我尚不清楚此内存泄漏是什么或如何解决的。

  • setenv()复制字符串,但我不知道它是如何工作的。进程加载时为环境分配了空间,但它是固定的。这里有一些(任意的)约定吗?例如,在env字符串指针数组中分配的插槽比当前使用的更多,并根据需要向下移动null终止指针?是否在环境本身的地址空间中分配了新的(复制的)字符串的内存,如果太大而无法容纳,您只需要获取ENOMEM?

  • 考虑到上述问题,有什么理由,更喜欢putenv()setenv()


问题答案:
  • [ putenv(char *string);…]呼叫似乎存在致命缺陷。

是的,它存在致命缺陷。 它被保留在POSIX(1988)中,因为那是现有技术。 该 setenv()机制稍后到达。 更正: POSIX
1990标准在§B.4.6.1中说:“ 已考虑但拒绝了附加函数putenv ()clearenv()
”。该单一Unix规格(SUS)第2版自1997年名单putenv(),但没有setenv()unsetenv()。下次修订版(2004)确实同时定义了setenv()unsetenv()

因为它不会复制传递的字符串,所以您不能使用本地调用它,并且不能保证分配给堆的字符串不会被覆盖或意外删除。

您是正确的,几乎总是将局部变量传递给它是一个错误的选择putenv()-异常情况几乎不存在,这是很难理解的。如果字符串是在堆上分配的(使用malloc()et等),则必须确保代码不会对其进行修改。如果是这样,它将同时修改环境。

此外(尽管我尚未测试过),因为环境变量的一种用法是将值传递给孩子的环境,如果孩子调用其中一个exec*()功能,这似乎毫无用处。我说错了吗?

这些exec*()函数复制环境并将其传递给执行的进程。那里没有问题。

Linux手册页指示glibc 2.0-2.1.1放弃了上述行为,并开始复制字符串,但这导致内存泄漏,该问题已在glibc
2.1.2中修复。我尚不清楚此内存泄漏是什么或如何解决的。

之所以会发生内存泄漏,是因为一旦调用putenv()了字符串,就无法再将该字符串用于任何用途,因为您无法确定该字符串是否仍在使用中,尽管可以通过覆盖它来修改该值(如果不确定,则结果不确定)。将名称更改为在环境中其他位置找到的环境变量的名称)。因此,如果您已分配空间,则经典putenv()变量会在您再次更改变量时泄漏。当putenv()开始复制数据时,已分配的变量变为未引用状态,因为putenv()不再保留对参数的引用,但用户希望环境将对其进行引用,因此内存被泄漏。我不确定解决方案是什么-
我会3/4期望它会恢复到旧的行为。

setenv()复制字符串,但我不知道它是如何工作的。进程加载时为环境分配了空间,但它是固定的。

原始环境空间是固定的;当您开始修改它时,规则会更改。即使使用putenv(),原始环境也会被修改,并且可能会由于添加新变量或由于将现有变量更改为更长的值而增长。

这里有一些(任意的)约定吗?例如,在env字符串指针数组中分配的插槽比当前使用的更多,并根据需要向下移动null终止指针?

这就是该setenv()机制可能要做的。(全局)变量environ指向环境变量的指针数组的开始。如果它一次指向一个内存块,而在另一时间指向另一个内存块,则将切换环境,就像这样。

是否在环境本身的地址空间中分配了新的(复制的)字符串的内存,如果太大而无法容纳,您只需要获取ENOMEM?

好吧,是的,您可以获得ENOMEM,但是您必须非常努力。而且,如果环境变得太大,则可能无法正确执行其他程序-环境将被截断或exec操作将失败。

考虑到上述问题,有什么理由比setenv()更喜欢putenv()吗?

  • setenv()在新代码中使用。
  • Update old code to use setenv(), but don’t make it a top priority.
  • Do not use putenv() in new code.


 类似资料:
  • 想改进这个问题吗?更新问题,使其仅通过编辑这篇文章来关注一个问题。 刚开始学习java大约一个月,我对arraylist和oop有几个问题 这个arraylist允许我将字符串添加到列表中并存储它,但是如果我有一个类调用簿呢 这三者有什么区别?假设我有大量的输入,比如文件 我有一个班级运动 我该怎么做呢?所以我用许多参数来添加这些输入,因为如果我想添加,我通常会这样做 我也会去

  • putenv(改变或增加环境变量) 相关函数 getenv,setenv,unsetenv 表头文件 #include4<stdlib.h> 定义函数 int putenv(const char * string); 函数说明 putenv()用来改变或增加环境变量的内容。参数string的格式为 name=value,如果该环境变量原先存在,则变量内容会依参数 string改变,否则此参数内容会

  • 此方法用于设置环境变量的值。 语法 (Syntax) putenv(‘name = value’) 参数 (Parameters) name - 环境变量的名称。 value - 环境变量的值。 返回值 (Return Value) 如果环境变量具有值,或者未定义此环境变量,则返回现有值,返回nullstring 。 例子 (Example) /* Main program */ optio

  • putenv 改变或增加环境变量 相关函数 getenv,setenv,unsetenv 表头文件 #include <stdlib.h> 定义函数 int putenv(const char *string); 函数说明 putenv()用来改变或增加环境变量的内容。参数string的格式为name=value,如果该环境变量原先存在,则变量内容会依参数string改变,否则此参数内容会成为

  • 本文向大家介绍关于Angular.js和Angular的问题相关面试题,主要包含被问及关于Angular.js和Angular的问题时的应答技巧和注意事项,需要的朋友参考一下 haizlin,你好,我想提一个建议。由于Angular和Angular.js是2个不同的框架,我建议要么将该Issue改为Angular面试题模版,要么新建一个Angular面试题模版。

  • 刚开始学习java大约一个月,我有几个关于arraylist和oop的问题 这个arraylist允许我将字符串添加到列表中并存储它,但是如果我有一个类调用簿呢 这三者有什么区别?假设我有大量的输入,比如文件 我有一个班级运动 我该怎么做呢?所以我用许多参数来添加这些输入,因为如果我想添加,我通常会这样做 我也会去