在 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