簡體   English   中英

char* 和帶有 std::getenv 的字符串之間的意外差異

[英]Unexpected difference between char* and string with std::getenv

我的代碼看起來像這樣:

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

std::string string_from_env(std::string var) {
  std::string out = std::getenv(var.c_str());
  return out;
}

int main() {
  const char* x1 = string_from_env("TEST_HOST").c_str();
  const char* x2 = string_from_env("TEST_USER").c_str();
  const char* x3 = string_from_env("TEST_NAME").c_str();

  std::cout << x1 << " " << x2 << " " << x3 << std::endl;

  const std::string y1 = string_from_env("TEST_HOST");
  const std::string y2 = string_from_env("TEST_USER");
  const std::string y3 = string_from_env("TEST_NAME");

  std::cout << y1 << " " << y2 << " " << y3 << std::endl;
}

如果我跑

export TEST_HOST=host
export TEST_USER=user
export TEST_NAME=name
g++ --std=c++2a test.cc  # version 9.3.0
./a.out

那么 output 是

name name name
host user name

為什么char*版本導致x1,x2,x3全部打印name ,而std::string版本按預期工作?

有沒有辦法可以修改string_from_env以便相同的代碼打印host user name而不是name name name

std::string::c_str返回的指針指向string object 擁有的 memory。 string被銷毀(或什至以某種方式發生變異)時,該指針變得無效。

由於在前三個調用中由string_from_env返回的臨時string對象不會立即綁定到引用,因此它們在包含 function 調用的完整表達式的末尾被銷毀。 這意味着x1x2x3在創建后立即變為無效。 嘗試從中讀取將導致未定義的行為。

考慮這條線

const char* x1 = string_from_env("TEST_HOST").c_str();

您不存儲調用string_from_env("TEST_HOST")的結果,因此它返回的臨時字符串將在表達式末尾被銷毀。 所以x1將指向一個已經被破壞的字符串的內部緩沖區。 您的代碼具有未定義的行為。

x1x2x3都指向同一個字符串的原因與小字符串優化有關,這是 std::string 的實現細節

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM