Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/156.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 将令牌强制转换为char*const时,使用boost标记化字符串失败*_C++_Boost_Boost Tokenizer - Fatal编程技术网

C++ 将令牌强制转换为char*const时,使用boost标记化字符串失败*

C++ 将令牌强制转换为char*const时,使用boost标记化字符串失败*,c++,boost,boost-tokenizer,C++,Boost,Boost Tokenizer,我使用 >在C++中标记字符串,然后将其传递给 ExcV< /Cord> 考虑以下代码段(可编译): #包括 #包括 #包括 #包括 //我将把每个标记都放入这个向量中 std::载体argc; //这是我要分析的命令 std::string命令=“/bin/ls-la-R”; 无效测试\标记器(){ //需要标记器,因为参数可以在引号中 boost::标记器脚本参数( 指挥部, boost::转义\u列表\u分隔符(“\\”,“,”); boost::tokenizer::迭代器参数; for

我使用 >在C++中标记字符串,然后将其传递给<代码> ExcV< /Cord> 考虑以下代码段(可编译):

#包括
#包括
#包括
#包括
//我将把每个标记都放入这个向量中
std::载体argc;
//这是我要分析的命令
std::string命令=“/bin/ls-la-R”;
无效测试\标记器(){
//需要标记器,因为参数可以在引号中
boost::标记器脚本参数(
指挥部,
boost::转义\u列表\u分隔符(“\\”,“,”);
boost::tokenizer::迭代器参数;
for(argument=scriptArguments.begin();
参数!=scriptArguments.end();
++(论据){
argc.push_back(参数->c_str());

std::cout c_str()

因此,当迭代器被修改时,
参数->c_str()
指向的字符数组可能会被修改或失效,其生存期最晚将以
参数的生存期结束

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


如果您想继续使用
boost::tokenizer
,我建议将令牌保存在
std::vector
中,然后将它们转换为指针数组。

挑剔之处:argc
的用法令人困惑,因为它通常用于
main()
的第二个参数。
\u exit()
是不可移植的;更喜欢(标准且功能相同的)
exit()
execv()
的使用应该
#包括
。构造
(char*const*)&argc[0]
在很多层次上都是错误的(至少有问题),无法在一个注释中解释。是的,避免使用C字符串(
char*
)在C++程序中,它们只会给你带来麻烦。-谢谢。如果有更合适的东西,我会高兴地放弃记录器。无论如何,把它们存储在向量中是很好的,但之后我必须为ReXV构建一个“conchchar *”数组。这里是相关的StAdExtOpLoad主题:所以我更喜欢“最近”或“现代”。丹IL:这里的问题是C++中“适当”和“方便”的转换,以及“代码> Excel())/>代码(“不是C,C++”)的“适当”。什么是前进的最佳方法取决于真正的用例…@ DeSun:是的,你完全正确。假设我有一个字符串变量命令。我想要执行这个命令。它可能包含参数,甚至在引号中。语言是C++,OS Linux。如果丹尼尔基本上是你想执行的任意shell命令,您可以简单地
execl
一个带有
-c
选项的shell,并将整个
命令作为单个参数传递。这样您就可以将问题委托给shell。(如果您不想在shell中创建子进程,请将
exec
前缀添加到
命令中。)如果
命令
来自不受信任的源,不应执行任意代码,请不要这样做。
#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);
}