繁体   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