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

Did the lifetime of c_str() changed between g++ 4.8.4 and g++ 5.3.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 编译的相同代码时,c_str() 指针失效.1.

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

reference 说:

The pointer obtained from c_str() may be invalidated by:

  • Passing a non-const reference to the string to any standard library function, or
  • Calling non-const member functions on the string, excluding operator[], at(), front(), back(), begin(), rbegin(), end() and rend().

P.S. 我已经有了一个修复,我现在对 c_str() 做了一个 stdup(),这样就可以正常工作了.只有我希望尽可能避免字符串的一个额外副本...

这里有两个问题:

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

首先,c_str()returns一个char const*args_p是一个vector<char*>。由于您需要指向非 const char 的指针,因此您将不得不使用 &a[0]

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

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