- mongodb - 在 MongoDB mapreduce 中,如何展平值对象?
- javascript - 对象传播与 Object.assign
- html - 输入类型 ="submit"Vs 按钮标签它们可以互换吗?
- sql - 使用 MongoDB 而不是 MS SQL Server 的优缺点
我一直在思考环境变量,并有一些问题/意见。
putenv(char *string);
这个调用似乎有致命的缺陷。因为它不复制传递的字符串,所以你不能用本地调用它,并且不能保证堆分配的字符串不会被覆盖或意外删除。此外(虽然我没有测试过),因为环境变量的一种用途是将值传递给 child 的环境,如果 child 调用 exec*()
函数之一,这似乎没用。我错了吗?
Linux 手册页表明 glibc 2.0-2.1.1 放弃了上述行为并开始复制字符串,但这导致了内存泄漏,已在 glibc 2.1.2 中修复。我不清楚这个内存泄漏是什么或如何修复的。
setenv()
复制字符串,但我不知道它是如何工作的。进程加载时为环境分配空间,但它是固定的。这里有一些(任意的?)约定吗?例如,在 env 字符串指针数组中分配比当前使用更多的插槽,并根据需要向下移动空终止指针?新的(复制的)字符串的内存是否分配在环境本身的地址空间中,如果它太大而无法容纳您只需获得 ENOMEM?
考虑到上述问题,有什么理由更喜欢 putenv()
而不是 setenv()
?
最佳答案
- [The]
putenv(char *string);
[...] call seems fatally flawed.
是的,它有致命的缺陷。 它被保存在 POSIX (1988) 中,因为那是现有技术。 更正: POSIX 1990 标准在 §B.4.6.1 中说“附加函数 putenv() 和 clearenv() 被考虑但被拒绝”。 Single Unix Specification (SUS) 1997 年的第 2 版列出了 setenv()
机制稍后出现。putenv()
,但没有列出 setenv()
或 unsetenv()
。下一个版本 (2004) 确实定义了 setenv()
和 unsetenv()
也是。
Because it doesn't copy the passed string you can't call it with a local and there is no guarantee a heap allocated string won't be overwritten or accidentally deleted.
你说得对,将局部变量传递给 putenv()
几乎总是一个糟糕的选择——异常模糊到几乎不存在的地步。如果字符串是在堆上分配的(使用 malloc()
等),您必须确保您的代码不会修改它。如果是,则同时在修改环境。
Furthermore (though I haven't tested it), since one use of environment variables is to pass values to child's environment this seems useless if the child calls one of the
exec*()
functions. Am I wrong in that?
exec*()
函数制作环境的副本并将其传递给执行的进程。那里没有问题。
The Linux man page indicates that glibc 2.0-2.1.1 abandoned the above behavior and began copying the string but this led to a memory leak that was fixed in glibc 2.1.2. It's not clear to me what this memory leak was or how it was fixed.
内存泄漏的出现是因为一旦你用一个字符串调用了 putenv()
,你就不能再出于任何目的使用该字符串,因为你无法判断它是否仍在使用,尽管你可以通过覆盖来修改值(如果将名称更改为在环境中另一个位置找到的环境变量的名称,则结果不确定)。所以,如果你已经分配了空间,经典的 putenv()
如果你再次更改变量就会泄漏它。当 putenv()
开始复制数据时,分配的变量变为未引用,因为 putenv()
不再保留对参数的引用,但用户期望环境将引用它,所以内存被泄露了。我不确定修复是什么——我 3/4 预计它会恢复到旧的行为。
setenv()
copies the string but I don't know exactly how that works. Space for the environment is allocated when the process loads but it is fixed.
原来的环境空间是固定的;当你开始修改它时,规则就会改变。即使使用 putenv()
,原始环境也会被修改,并且可能会因添加新变量或将现有变量更改为更长的值而增长。
Is there some (arbitrary?) convention at work here? For example, allocating more slots in the env string pointer array than currently used and moving the null terminating pointer down as needed?
这就是 setenv()
机制可能会做的事情。 (全局)变量 environ
指向环境变量指针数组的开头。如果它一次指向一个内存块,另一个时间指向另一个 block ,那么环境就被切换了,就这样。
Is the memory for the new (copied) string allocated in the address space of the environment itself and if it is too big to fit you just get ENOMEM?
嗯,是的,您可以获得 ENOMEM,但您必须非常努力。如果你将环境扩展得太大,你可能无法正确执行其他程序——要么环境被截断,要么执行操作失败。
Considering the above issues, is there any reason to prefer putenv() over setenv()?
setenv()
。setenv()
,但不要将其作为首要任务。putenv()
。关于c - 关于 putenv() 和 setenv() 的问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5873029/
在我的 apache 实例上,它设置了一个环境变量 APP_ENV=development。我正在尝试在我的 PHP 端动态更改此设置(在启动测试套件的实例中),如下所示: putenv('APP_E
我正在尝试使用 GCC 4.7.1 (MinGW) 在 Windows 上编译 Qt 4.8.4。我编辑了 mkspec 以包含 C++11 特性(添加了 -std=c++11 标志)来编译 Java
当 php用作 apache模块,来自 apache 的环境变量 SetEnv指令可用于 php 的 getenv() , 但它似乎不适用于 C通过 stdlib 的 getenv() 扩展.至少它发
我在这里阅读了几篇文章,但仍然对 setenv() 的方式感到困惑作品: linux-where-are-environment-variables-stored where-is-the-envir
编辑:据我所知,我的问题是由于 PHP 的缺陷造成的。我已将此问题复制到 PHP 错误跟踪器:https://bugs.php.net/bug.php?id=74143并计划尝试实现修复。 puten
函数 putenv 不是线程安全函数,所以我想如果我在调用 putenv 之前调用 pthread_mutex_lock,我可以让 putenv 这样“线程安全”? 我试过了,但是当我运行它的时候,出
我需要用户在文本文件中定义我的程序所需的所有环境变量,如下所示。 MyDLLPath = C:\MyDLLPath 我的选项 = 选项 1 PATH = %MyDLLPath%;%PATH%; 在我的
我正在为系统编程类(class)开发自定义 shell。我们被指示实现内置的 setenv() 和 unsetenv() 命令,并提示检查 putenv()。 我的问题是 setenv(char*,
POSIX 系统调用 putenv 声明分配的内存字符串在调用 putenv 后不能被调用者释放。因此,您不能使用自动变量调用 putenv。 例子: #include #include #inc
putenv函数接受一个参数,一个字符串。此字符串应采用以下格式:KEY=VALUE . 引用:http://php.net/manual/en/function.putenv.php 将以下代码作为
我提前为一些代码转储道歉,我已经尽可能多地修剪了不重要的代码: // Global vars / mutex stuff extern char **environ; pthread_mutex_t
我正在学习 Laravel。我使用 WinNMP 安装了 php 7、mysql 和 nginx。我安装了composer,并通过它安装了laravel cli(Laravel\Installer)。
我需要从用户那里获取输入并处理变量。我需要具备以下功能: set varname = somevalue:将名为varname的环境变量的值设置为somevalue指定的值。 delete varna
在 php 中,运行: echo shell_exec("export http_proxy=http://myproxy.com:8080 2>&1"); echo shell_exec("env
尝试运行以下在 VS2012 中编译的代码时,我似乎遇到了内存损坏。 它在 VS2010 和以前的版本中工作正常: char *var1 = getenv("var1"); // Value for
我正在尝试在使用 g++ 编译的程序中使用 putenv stdlib 函数,包括标志和警告 - std=c++11 和 -Wall -Wextra。 程序可以像下面这样简单: #include #i
我尝试在 Ubuntu 13.04(64 位)上使用 gcc 4.7.3 和 clang 3.2.1 编译以下代码: #include #include #include int main()
我一直在思考环境变量,并有一些问题/意见。 putenv(char *string); 这个调用似乎有致命的缺陷。因为它不复制传递的字符串,所以你不能用本地调用它,并且不能保证堆分配的字符串不会被覆盖
我试图通过在此之前连接 str1 和 str2 在 UNIX 上使用 putenv() 。 我想在环境中添加一个变量或修改一个变量,所以我调用 putenv() (或者我可以调用 setenv() 相
pytest 的 monkeypatch模块提供了一个setenv 函数,它将设置环境变量名称为值。 为什么monkeypatch 提供这个?听起来和os.putenv一样?它提供了 prepend
我是一名优秀的程序员,十分优秀!