字符串拆分为vector <char *>会覆盖矢量元素

时间:2016-10-01 22:45:59

标签: c++ string

使用https://stackoverflow.com/a/236803/6361644中提到的以下代码,我编写了以下代码来将字符串解析为向量,其中每个元素由空格分隔。

std::string line = "ls -l -a";
std::string cmd;
std::vector<char*> argv;
std::stringstream ss;
ss.str(line); 
std::string tmp;
getline(ss, cmd, ' ');
argv.push_back( const_cast<char*>(cmd.c_str() ) );
while(getline(ss, tmp, ' '))
    argv.push_back( const_cast<char*>(tmp.c_str() ) );
argv.push_back(NULL);

在此代码之后打印argv

{gdb) print argv                                                                         
$22 = std::vector of length 3, capacity 4 = {0x26014 "ls", 0x2602c "-a", 0x2602c "-a", 0x0} 

我不确定为什么要覆盖第二个元素。任何提示将不胜感激。

2 个答案:

答案 0 :(得分:2)

你正在存储悬空指针(以不正确的方式存储!存储指向c风格字符串的指针的正确方法是const char*,而不是char*)。

在此(const - 更正的)循环中:

std::vector<const char*> argv;
// ...
while(getline(ss, tmp, ' '))
    argv.push_back(tmp.c_str());

每次后续迭代都将清除tmp,使您存储的先前指针无效。您推回的每个tmp.c_str()都会被getline()立即释放。因此,所有后续访问都是未定义的。

你必须取得所有字符串的所有权,你可以通过存储完整的string来实现这一点:

std::vector<std::string> argv;
// ...
while(getline(ss, tmp, ' '))
    argv.push_back(std::move(tmp));

现在argv实际上拥有自己的所有资源。

答案 1 :(得分:-1)

c_str()返回的指针指向std::string的内部数据。

此指针仅在字符串被销毁或修改之前有效。一旦std::string被销毁或修改,指针就不再有效了。

while(getline(ss, tmp, ' '))
    argv.push_back( const_cast<char*>(tmp.c_str() ) );

抛开抛出const - ness的问题,这已经是一个红旗:每次while循环迭代时tmp的内容被下一行替换在ss文件中。

这会自动使在c_str()循环的上一次迭代中获得的while无效。

这里正确的解决方案是首先将所有单个单词解析为std::vector<std::string>

然后,初始化此向量后,迭代向量并获取每个单独的字符串c_str(),以构造原始字符指针的向量。

更好:使用std::vector<char>代替std::string,添加明确的&#39; \ 0&#39;每个向量末尾的字符,丑陋的const_cast不是必需的。

相关问题