在 C++ 中获取环境变量

Jinku Hu 2023年10月12日
  1. 使用 std::getenv 函数访问 C++ 中的环境变量
  2. 使用自定义检查例程来验证有效的环境变量值
在 C++ 中获取环境变量

本文将介绍几种在 C++ 中获取环境变量的方法。

使用 std::getenv 函数访问 C++ 中的环境变量

getenv 是在 C 标准库中实现的符合 POSIX 标准的函数,可以在 C++ 源文件中使用 <cstdlib> 头文件导入。该函数将字符串作为唯一的参数,并搜索与之相等的环境变量名。

环境变量通常用大写字母表示,但 getenv 仍然要求参数字符串不能用小写字母,因为即使它在程序环境中定义了,也不会与变量名匹配。函数返回的是 char*类型,对应的变量值就存放在这个类型中。

注意,我们将 getenv 的返回值分配给 const char*变量,因为我们需要确保程序不会修改该位置,否则会导致未定义的行为。

#include <cstdlib>
#include <iostream>
#include <string>

using std::cerr;
using std::cout;
using std::endl;
using std::getenv;
using std::string;

const char *ENV_VAR = "HOME";

int main() {
  const char *tmp = getenv("HOME");
  string env_var(tmp ? tmp : "");
  if (env_var.empty()) {
    cerr << "[ERROR] No such variable found!" << endl;
    exit(EXIT_FAILURE);
  }

  cout << "HOME : " << env_var << endl;

  exit(EXIT_SUCCESS);
}

输出:

HOME : /home/username

同样重要的是不要将 getenv 函数返回的值直接传递给 std::string 构造函数,因为当 getenv 函数不能计算任何环境变量时,可能会抛出一个分段故障。

这个问题是在 std::string 构造函数代码的实现中引起的,它在下面调用了 std::char_traits::length() 函数。如果将 nullptr 作为参数传递给它,后一个函数将导致未定义的行为。因此,就出现了这样的情况:当找不到环境变量时,getenv 可以返回 nullptr,如果我们把它传给 string 构造函数,就会形成错误的代码。

#include <cstdlib>
#include <iostream>
#include <string>

using std::cerr;
using std::cout;
using std::endl;
using std::getenv;
using std::string;

const char *ENV_VAR = "HOME";

int main() {
  // Erroneous
  string env_var(getenv("HOME"));
  if (env_var.empty()) {
    cerr << "[ERROR] No such variable found!" << endl;
    exit(EXIT_FAILURE);
  }

  cout << "HOME : " << env_var << endl;

  exit(EXIT_SUCCESS);
}

使用自定义检查例程来验证有效的环境变量值

在访问环境变量时,最危险的陷阱之一是验证检索的值。请注意,这些变量可能被攻击者在我们的程序范围之外进行操作。因此,需要对这些值进行额外的消毒,以确保程序执行的正确和安全。

这些检查例程主要是依赖于程序的,应该针对每种情况进行不同的处理。在下面的例子中,我们演示了这样的情况:我们假设字符串值中不应该有任何空格,如果有,我们就提取第一个空格字符之前的子字符串。通过这种方式,我们回避了系统环境中任何不规则的输入值。注意,std::find 算法被用来搜索 string 中的字符,如果没有找到指定的 char,它将返回 string::npos

#include <algorithm>
#include <cstdlib>
#include <iostream>
#include <string>

using std::cerr;
using std::cout;
using std::endl;
using std::find;
using std::getenv;
using std::string;

const char *ENV_VAR = "HOME";

int main() {
  const char *tmp = getenv(ENV_VAR);
  string env_var(tmp ? tmp : "");
  if (env_var.empty()) {
    cerr << "[ERROR] No such variable found!" << endl;
    exit(EXIT_FAILURE);
  }

  // Env Variable Value Sanitization
  int pos = env_var.find(' ');
  if (pos != string::npos) env_var = env_var.substr(0, pos);

  cout << "HOME : " << env_var << endl;

  exit(EXIT_SUCCESS);
}
作者: Jinku Hu
Jinku Hu avatar Jinku Hu avatar

DelftStack.com 创始人。Jinku 在机器人和汽车行业工作了8多年。他在自动测试、远程测试及从耐久性测试中创建报告时磨练了自己的编程技能。他拥有电气/电子工程背景,但他也扩展了自己的兴趣到嵌入式电子、嵌入式编程以及前端和后端编程。

LinkedIn Facebook