3

如果后者通过可选getenv()参数传递给?envz_get()envpint main (int argc, char *argv[], char *envp[])

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

4

3 回答 3

1

根据我的经验,是的,它们是相同的。如果不是,getenv() 似乎不会特别有用。这不是我几十年来测试过的东西,但是为了回答你的问题,我只是进行了一个测试,虽然标准允许 getenv() 使用静态内存区域进行返回,但它的返回值都指向到 main 的第三个参数中等号之后的第一个字符。这是我模糊的回忆,这也发生在我最后一次做这个测试时,虽然那是一个不同的 unix 系统。

话虽如此,看看标准,或者尽可能接近我可以合理地得出的结论......来自最后一个免费提议的 C17 草案:

getenv 函数在主机环境提供的环境列表中搜索与 name 指向的字符串匹配的字符串。环境名称集和更改环境列表的方法是实现定义的。getenv 函数不需要避免与修改环境列表的其他执行线程的数据竞争。305)

实现的行为就像没有库函数调用 getenv 函数一样。返回 getenv 函数返回一个指向与匹配列表成员关联的字符串的指针。指向的字符串不应被程序修改,但可能会被后续调用 getenv 函数覆盖。如果找不到指定的名称,则返回空指针。

305) 许多实现提供了修改环境列表的非标准功能。

这基本上意味着,可能,但 C 语言并不能完全保证它。

于 2019-02-07T07:29:12.220 回答
1

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

在我的系统上,它会打印:

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
于 2019-02-09T17:46:08.823 回答
0

以下证明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
于 2019-02-08T06:33:40.600 回答