【问题标题】:Getting C-string from local copy of returned std::string从返回的 std::string 的本地副本中获取 C 字符串
【发布时间】:2013-04-30 04:22:59
【问题描述】:

我正在尝试调试与包含在 std::string 中的字符数组的范围相关的问题。我已经在下面发布了相关的代码示例,

#include <iostream>
#include <string>

const char* objtype;

namespace A
{

std::string get_objtype()
{
  std::string result;
  std::string envstr( ::getenv("CONFIG_STR") );
  std::size_t pos1 = 0, pos2 = 0, pos3 = 0;
  pos1 = envstr.find_first_of("objtype");
  if (pos1 != std::string::npos)
    pos2 = envstr.find_first_of("=", pos1+7);
  if (pos2 != std::string::npos)
  {
    pos3 = envstr.find_first_of(";", pos2+1);
    if (pos3 != std::string::npos)
      result = envstr.substr(pos2+1, pos3 - pos2 - 1);
  }
  const char* result_cstr = result.c_str();
  std::cerr << "get_objtype()" << reinterpret_cast<long>((void*)result_cstr) << std::endl;
  return result;
}

void set_objtype()
{
  objtype = get_objtype().c_str();
  std::cerr << "Objtype " << objtype << std::endl;
  std::cerr << "main()" << reinterpret_cast<long>((void*)objtype) << std::endl;
}

}

int main()
{
  using namespace A;
  std::cerr << "main()" << reinterpret_cast<long>((void*)objtype) << std::endl;
  set_objtype();

  if (::strcmp(objtype, "AAAA") == 0)
    std::cerr << "Do work for objtype == AAAA " << std::endl;
  else
    std::cerr << "Do work for objtype != AAAA" << std::endl;
}

这是在带有 g++ 4.2.1 的 MacOS 12.3 上编译和执行的。运行this的输出如下,

$ g++ -g -DNDEBUG -o A.exe A.cpp
$ CONFIG_STR="objtype=AAAA;objid=21" ./A.exe
main()0
get_objtype()140210713147944
Objtype AAAA
main()140210713147944
Do work for objtype == AAAA
$

我的问题是: 从 main() 和 get_objtype() 打印的指针值是相同的。这是由于 RVO 造成的吗? 最后一行输出表明,即使封闭的 std::string 超出范围,指向 C 字符串的全局指针也可以。那么,什么时候返回值超出范围,字符串数组被删除呢?感谢社区提供的任何帮助。谢谢。

【问题讨论】:

  • get_objtype() 中返回的字符串在语句之后立即被销毁。即在击中分号之后。只是 objtype 指向的地址没有被任何其他数据覆盖。因此,您仍然会看到值“AAAA”。
  • 顺便说一句,你想用这个例子实现什么?除非你做一些不同的事情,否则让代码更简单。
  • 我正在尝试理解现有的一段代码。
  • 在 Mac OS 12.3 上编译并执行?什么时候出来的?
  • @迈克尔。你没有得到这个输出吗?

标签: c++ return-value-optimization


【解决方案1】:

指针值不会改变,但它指向的内存可能不再是字符串的一部分。

objtypeset_objtype() 中设置后立即在行上无效,因为 get_objtype() 的结果没有保存在任何地方,所以编译器可以随意杀死它。

它可能会工作,但它访问的是无效内存,所以它是无效代码,如果你依赖这样的东西,你最终会遇到大问题。

【讨论】:

  • 谢谢。那么编译器会在调用 c_str() 之前创建一个临时字符串吗?
  • objtype = get_objtype().c_str();行上的分号之前,有一个匿名字符串“存在”。get方法返回一个实际的字符串(在堆栈上)。
【解决方案2】:

您应该使用 objdump 查看反汇编,以检查其是否为 RVO。

但是,根据我所做的实验(使结果全局化并复制它),看起来 c_str 是引用计数的。

【讨论】:

    猜你喜欢
    • 2011-04-12
    • 2021-12-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-01-07
    • 1970-01-01
    相关资源
    最近更新 更多