c_str()的生命周期是否在g ++ 4.8.4和g ++ 5.3.1之间发生了变化?

时间:2016-05-08 20:42:37

标签: c++ string g++ g++4.8 g++5.1

我从一个守护进程启动进程,确保所述进程连续运行并以正确的顺序开始,等等。

在某些时候,我想用execv()启动进程,所以我为参数准备了一个字符串数组:

std::vector<std::string> args;
args.push_back("--debug");
args.push_back("--connect");
args.push_back("10.0.0.5:4040");
...

在大多数情况下,我有大约10个这样的论点。

现在,execv()只访问一个裸指针数组。所以我执行以下操作来创建这样的指针数组:

std::vector<char *> args_p; // sorry, my code actually uses std::vector<char const *> args_p -- so constness is fine here
for(auto a : args)
{
    args_p.push_back(a.c_str());
}
args_p.push_back(nullptr); // list needs to be null terminated

然后我可以用最后一个数组调用execv()

execv(
    args_p[0],
    const_cast<char * const *>(&args_p[0])
);

这在Ubuntu 14.04中使用g ++ 4.8.4完美地工作,但不知何故,当我尝试运行使用g ++ 5.3.1编译的相同代码时,c_str()指针无效。

根据我的理解,这不应该是因为我不修改创建裸指针数组的第一个循环和execv()调用之间的字符串。

reference说:

  

从c_str()获得的指针可以通过以下方式无效:

     
      
  • 将对字符串的非const引用传递给任何标准库函数,或
  •   
  • 在字符串上调用非const成员函数,不包括operator [],at(),front(),back(),begin(),rbegin(),end()和rend()。
  •   

P.S。我已经有了修复,我现在执行了stdup()的{​​{1}},这样就可以了。只有我希望在可能的情况下避免使用一个额外的字符串副本......

1 个答案:

答案 0 :(得分:2)

这里有两个问题:

for(auto a : args)
{
    args_p.push_back(a.c_str());
}

首先,c_str()返回char const*args_pvector<char*>。由于您需要指向非const char的指针,因此您必须使用&a[0]

其次,a在循环的每次迭代结束时超出范围。所以你所掌握的指针会从你身下被摧毁。你需要指向args中实际字符串的指针 - 所以你需要通过引用迭代:

for(auto& a : args)
{
    args_p.push_back(&a[0]);
}