envz_get 和 getenv 是否引用相同的环境变量池?

Do envz_get and getenv reference the same pool of environment variables?

如果将可选的 envp 参数传递给 int main (int argc, char *argv[], char *envp[])?[=18=,getenv()envz_get() 都从同一来源查找环境变量]

换句话说,int main (int argc, char *argv[], char *envp[]) 的可选 envp 参数是否指的是 getenv() 引用的同一个环境变量池?

根据我的经验,是的,它们是相同的。如果不是这样, getenv() 似乎不会特别有用。这不是我几十年来测试过的东西,但为了回答你的问题,我只是 运行 一个测试,而标准允许 getenv() 为其 [=17 使用静态内存区域=]s,它的return值都指向main的第三个参数中等号后的第一个字符。我模糊地记得上次我做这个测试时也发生过这种情况,虽然那是一个不同的 unix 系统。

话虽这么说,看看标准,或者我能合理地得出的最接近标准...来自上次免费提议的 C17 草案:

The getenv function searches an environment list, provided by the host environment, for a string that matches the string pointed to by name . The set of environment names and the method for altering the environment list are implementation-defined. The getenv function need not avoid data races with other threads of execution that modify the environment list. 305)

The implementation shall behave as if no library function calls the getenv function. Returns The getenv function returns a pointer to a string associated with the matched list member. The string pointed to shall not be modified by the program, but may be overwritten by a subsequent call to the getenv function. If the specified name cannot be found, a null pointer is returned.

305) Many implementations provide non-standard functions that modify the environment list.

这基本上意味着,可能,但 C 语言并不完全 gua运行tee 它。

以下证明 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;
}

.

> g++ main.cpp && ./a.exe
true

当前进程状态下环境变量使用的字符串不一定在连续的内存中。某些环境变量可能已被启动代码删除,或者通过调用 putenvsetenv 更改或添加。这些更改不一定反映在 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