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