Envz_get и getenv ссылаются на один и тот же пул переменных среды? - PullRequest
0 голосов
/ 07 февраля 2019

Do getenv() и envz_get() оба ищут переменные среды из одного и того же источника, если последнему передается необязательный аргумент envp в int main (int argc, char *argv[], char *envp[])?

Другими словами, делает ли необязательный envp аргумент int main (int argc, char *argv[], char *envp[]) относится к тому же пулу переменных среды, на который ссылается getenv()?

Ответы [ 3 ]

0 голосов
/ 08 февраля 2019

Следующее доказывает, что 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
0 голосов
/ 09 февраля 2019

Строки, используемые переменными среды в текущем состоянии процесса, не обязательно находятся в непрерывной памяти.Некоторые переменные среды могут быть удалены кодом запуска, изменены или добавлены путем вызова 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
0 голосов
/ 07 февраля 2019

По моему опыту, да, они идентичны.Не похоже, что getenv () был бы особенно полезен, если бы не было.Это не то, что я тестировал десятилетиями, но в ответ на ваш вопрос я просто запустил тест, и, хотя стандарт getenv () разрешает использовать статическую область памяти для своих возвратов, все возвращаемые значения указаныдо первого символа после знака равенства в третьем аргументе в main.Это мое смутное воспоминание, это произошло в прошлый раз, когда я тоже проводил этот тест, хотя это была другая система Unix.

Сказано, глядя на стандарт, или настолько близко, насколько я могу обоснованно прийти к этому.... Из последнего предложенного свободного варианта C17:

Функция getenv ищет в списке среды, предоставленном хост-средой, строку, соответствующую строке, указанной в имени.Набор имен среды и метод для изменения списка среды определяются реализацией.Функция getenv не должна избегать скачек данных с другими потоками выполнения, которые изменяют список среды.305)

Реализация должна вести себя так, как будто ни одна библиотечная функция не вызывает функцию getenv.Возвращает Функция getenv возвращает указатель на строку, связанную с соответствующим элементом списка.Указанная строка не должна изменяться программой, но может быть перезаписана последующим вызовом функции getenv.Если указанное имя не может быть найдено, возвращается нулевой указатель.

305) Многие реализации предоставляют нестандартные функции, которые изменяют список среды.

Что в основном означает, вероятно,но язык Си точно не гарантирует этого.

...