我正在尝试调试与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;
}
这是在MacOS 12.3和g++ 4.2.1上编译和执行的。运行该命令的输出如下所示,
$ 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-string的全局指针也是可以的。那么,返回值何时超出作用域并删除字符串数组?感谢来自社区的任何帮助。谢谢。
指针的值不会改变,但它指向的内存可能不再是字符串的一部分。
objtype
在set_objtype()
中设置后的行上无效,因为get_objtype()的结果没有保存在任何地方,因此编译器可以自由地在那里杀死它。
它可能工作,但它访问无效的内存,所以它是无效的代码,如果你依赖这样的东西,你最终会遇到大问题
您应该使用objdump查看反汇编,以检查它是否为RVO。
但是,从我做的实验(使结果全局并复制它),它看起来像c_str是引用计数的。