[英]String split into vector<char*> overwrites vector elements
使用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}
我不确定为什么第二个元素被覆盖。 任何提示将不胜感激。
您正在存储悬空指针(以格式错误的方式存储!存储指向 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
实际上拥有自己的所有资源。
c_str()
返回的指针指向std::string
的内部数据。
该指针仅在字符串被销毁或修改之前有效。 一旦std::string
被销毁或修改,指针就不再有效。
while(getline(ss, tmp, ' '))
argv.push_back( const_cast<char*>(tmp.c_str() ) );
抛开转换const
-ness 的问题,这已经是一个危险信号:每次while
循环迭代tmp
的内容时,都会被ss
文件中的下一行替换。
这会自动使在while
循环的前一次迭代中获得的c_str()
无效。
这里的正确解决方案是首先将所有单个单词解析为std::vector<std::string>
。
然后,一旦这个向量被初始化,迭代这个向量并获得每个单独的字符串的c_str()
,以构造原始字符指针的向量。
更好的是:使用std::vector<char>
而不是std::string
,在每个向量的末尾添加一个显式的 '\\0' 字符,并且不需要丑陋的const_cast
。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.