将令牌强制转换为char * const *时,带有boost的令牌化字符串失败

时间:2019-09-17 20:48:49

标签: c++ boost boost-tokenizer

我正在使用boost::tokenizer在C ++中标记字符串,然后将其传递给execv

考虑以下代码片段(可编译):

#include <iostream>
#include <cstdlib>
#include <vector>
#include <boost/tokenizer.hpp>

// I will put every token into this vector
std::vector<const char*> argc;
// this is the command I want to parse
std::string command = "/bin/ls -la -R";


void test_tokenizer() {
  // tokenizer is needed because arguments can be in quotes
  boost::tokenizer<boost::escaped_list_separator<char> > scriptArguments(
              command,
              boost::escaped_list_separator<char>("\\", " ", "\""));
  boost::tokenizer<boost::escaped_list_separator<char> >::iterator argument;
  for(argument = scriptArguments.begin(); 
    argument!=scriptArguments.end(); 
    ++argument) {

    argc.push_back(argument->c_str());
    std::cout << argument->c_str() << std::endl;
  }

  argc.push_back(NULL);
}

void test_raw() {
  argc.push_back("/bin/ls");
  argc.push_back("-l");
  argc.push_back("-R");

  argc.push_back(NULL);
}

int main() {
  // this works OK
  /*test_raw();
  execv(argc[0], (char* const*)&argc[0]);
  std::cerr << "execv failed";
  _exit(1);
  */

  // this is not working
  test_tokenizer();
  execv(argc[0], (char* const*)&argc[0]);
  std::cerr << "execv failed";
  _exit(2);
}

当我运行此脚本时,它将调用test_tokenizer(),它将显示“ execv failed”。 (尽管它很好地显示了参数)。

但是,如果我将test_tokenizer更改为test_raw,它将运行正常。

必须是一些简单的解决方案,但我没有找到它。

PS ::我还将其放入具有增强支持here的在线编译器中。

1 个答案:

答案 0 :(得分:3)

boost::tokenizer将令牌按值(默认为std::string)保存在令牌迭代器中。

因此,argument->c_str()指向的字符数组在修改迭代器时可能会被修改或无效,并且其生存期最迟将以argument结束。

因此,当您尝试使用argc时,程序具有未定义的行为。

如果您想继续使用boost::tokenizer,我建议将标记保留在std::vector<std::string>中,然后将其转换为指针数组。