C envz_get和getenv引用相同的环境变量池吗?
如果将可选的C envz_get和getenv引用相同的环境变量池吗?,c,glibc,getenv,C,Glibc,Getenv,如果将可选的envp参数传递给int-main(int-argc,char*argv[],char*envp[]),则执行getenv()和envz_get()查找来自同一源的环境变量。 换句话说,int main(int argc,char*argv[],char*envp[])的可选envp参数是否引用了由getenv()引用的相同环境变量池?根据我的经验,是的,它们是相同的。如果不是的话,getenv()似乎不是特别有用。这不是我几十年来一直在测试的东西,但为了回答您的问题,我刚刚运行了一
envp
参数传递给int-main(int-argc,char*argv[],char*envp[]),则执行getenv()
和envz_get()
查找来自同一源的环境变量。
换句话说,
int main(int argc,char*argv[],char*envp[])
的可选envp
参数是否引用了由getenv()
引用的相同环境变量池?根据我的经验,是的,它们是相同的。如果不是的话,getenv()似乎不是特别有用。这不是我几十年来一直在测试的东西,但为了回答您的问题,我刚刚运行了一个测试,虽然标准允许getenv()使用静态内存区域进行返回,但它的返回值都指向main的第三个参数中等号后的第一个字符。这是我模糊的记忆,上次我做这个测试时也发生了这种情况,尽管那是一个不同的unix系统
话虽如此,看看标准,或者尽我所能合理地得出。。。从上一次自由提议的C17草案:
getenv函数在宿主环境提供的环境列表中搜索
匹配名称指向的字符串。环境名称集和更改方法
环境列表是实现定义的。getenv函数不需要避免数据争用
使用修改环境列表的其他执行线程。305)
该实现的行为应与没有库函数调用getenv函数一样。
退换商品
getenv函数返回指向与匹配列表成员关联的字符串的指针。这个
指向的字符串不能被程序修改,但可以被后续调用覆盖
到getenv函数。如果找不到指定的名称,则返回空指针
305)许多实现提供了修改环境列表的非标准函数
这基本上意味着,可能是这样,但C语言并不能完全保证这一点。下面证明了
envp
引用的池至少是getenv()
从中提取的池的子集;我倾向于认为,实际上,它们是完全相同的
#include <iostream>
#include <vector>
int main( int argc, char* argv[], char* envp[] )
{
std::vector<std::string> fromEnvP;
while ( *envp ) fromEnvP.push_back( *envp++ );
std::vector<std::string> fromEnv;
for( std::vector<std::string>::iterator i = fromEnvP.begin();
i != fromEnvP.end();
++i )
{
std::string::size_type pos = i->find( '=' );
std::string varname( i->substr( 0, pos ) );
fromEnv.push_back( varname + "=" + getenv( varname.c_str() ) );
}
std::cout << std::boolalpha << ( fromEnvP == fromEnv ) << std::endl;
return 0;
}
当前进程状态中环境变量使用的字符串不一定在连续内存中。某些环境变量可能已被启动代码删除,或通过调用
putenv
或setenv
更改或添加。这些更改不一定反映在envz_get
检查的字符串数组中,因为它们是通过更改环境数组中的指针(而不是字符串)来执行的
下面是一个示例,演示了这一点:
#include <assert.h>
#include <envz.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int
main (int argc, char **argv, char **envp)
{
assert (envp[0] != NULL);
assert (envp[1] != NULL);
char *first_name = strndup (envp[0], strcspn (envp[0], "="));
char *second_name = strndup (envp[1], strcspn (envp[1], "="));
printf ("removing: %s\n", second_name);
unsetenv (second_name);
printf ("getenv (%s): %s\n", first_name, getenv (first_name));
size_t size = 0;
for (size_t i = 0; envp[i] != NULL; ++i)
size += strlen (envp[i]) + 1;
printf ("envz_get (%s): %s\n",
first_name, envz_get (envp[0], size, first_name));
printf ("getenv (%s): %s\n",
second_name, getenv (second_name));
printf ("envz_get (%s): %s\n",
second_name, envz_get (envp[0], size, second_name));
}
您是否尝试打印每个
envp
的指针地址并查看其存储位置?程序将envp
数组的内容与getenv
返回的内容进行比较。这不是问题所在envz_get
执行其他操作。
#include <assert.h>
#include <envz.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int
main (int argc, char **argv, char **envp)
{
assert (envp[0] != NULL);
assert (envp[1] != NULL);
char *first_name = strndup (envp[0], strcspn (envp[0], "="));
char *second_name = strndup (envp[1], strcspn (envp[1], "="));
printf ("removing: %s\n", second_name);
unsetenv (second_name);
printf ("getenv (%s): %s\n", first_name, getenv (first_name));
size_t size = 0;
for (size_t i = 0; envp[i] != NULL; ++i)
size += strlen (envp[i]) + 1;
printf ("envz_get (%s): %s\n",
first_name, envz_get (envp[0], size, first_name));
printf ("getenv (%s): %s\n",
second_name, getenv (second_name));
printf ("envz_get (%s): %s\n",
second_name, envz_get (envp[0], size, second_name));
}
removing: LESSCLOSE
getenv (STY): 9173.pts-0.deneb
envz_get (STY): 9173.pts-0.deneb
getenv (LESSCLOSE): (null)
envz_get (LESSCLOSE): /usr/bin/lesspipe %s %s