简体   繁体   English

我如何以可靠的方式将 std::vector 转换为 char **?

[英]how do i convert std::vector to char ** in a reliable way?

I have been trying to avoid using char ** arrays, however because i am using execvp, i wrote a method to convert a vector of strings to a null terminated char **.我一直在尝试避免使用 char ** 数组,但是因为我使用的是 execvp,所以我编写了一个方法将字符串向量转换为空终止的 char **。

Unfortunately i have until recently been getting segmentation faults, which makes me suspicious that my method doesn't always work for one reason or another:不幸的是,直到最近我才遇到分段错误,这让我怀疑我的方法由于某种原因并不总是有效:

void vectorToNullArray(std::vector<std::string> const &v, char **a) {
  int i = 0;
  while (i < v.size()) {
    std::string str = v[i];
    char *cstr = new char[str.size()+1];
    strcpy(cstr, str.c_str());
    a[i] = cstr;                       // <-- segfault here
    i++;
  }
  a[i] = nullptr;
}

if i can be completely free of char ** in the first place, that would be ideal.如果我首先可以完全摆脱 char **,那将是理想的。 Why is this code segfaulting?为什么这段代码会出现段错误?

EDIT: this is how i call it:编辑:这就是我所说的:

  char **argvA;
    vectorToNullArray(_ARGV, argvA);

where _ARGV is an std::vector<std::string> , a member variable of some class.其中_ARGVstd::vector<std::string> ,某个类的成员变量。

EDIT 2: working solution编辑 2:工作解决方案

std::vector<char *> nullTerminatedArgV(std::vector<std::string> const &v) {
  std::vector<char *> result;
  for (auto const &s : v) {
    result.push_back(const_cast<char *>(s.c_str()));
  }
  result.push_back(nullptr);
  return result;
}

usage with execvp:与 execvp 一起使用:

    std::vector<char *> argv = nullTerminatedArgV(_ARGV);
    char **command = argv.data();

      int status = execvp(command[0], command);
      perror("execvp error");

essentially the accepted answer, with additions from here:基本上是公认的答案,从这里补充:

https://stackoverflow.com/a/47714627/5133238 https://stackoverflow.com/a/47714627/5133238

As Pete Becker says, the issue's probably that you haven't called it properly - and specifically that the a argument doesn't point to a sufficiently large array of char* s to write to.正如皮特贝克尔所说,问题可能是你没有正确调用它 - 特别是a参数没有指向足够大的char*数组来写入。

Anyway, do you really need to screw around with dynamic memory allocation here?无论如何,您真的需要在这里进行动态内存分配吗? Having std::vector manage memory for you is much easier, safer, and more concise.std::vector为您管理内存更容易、更安全、更简洁。 Perhaps you can do something like below, then pass the result's .data() value to execvp ?也许您可以执行以下操作,然后将结果的.data()值传递给execvp You do need to make sure the vector of strings passed as an argument is not mutated by the caller after this call and before calling execvp , otherwise the pointers you collect may be invalidated.您确实需要确保在此调用之后和调用execvp之前,作为参数传递的字符串向量不会被调用者改变,否则您收集的指针可能会失效。

std::vector<const char*> getVectorOfPointersToStrings(std::vector<std::string> const& v) {
    std::vector<const char*> result;
    for (const auto& s : v)
        result.push_back(s.c_str());
    result.push_back(nullptr);
    return result; 
}
char **argvA;
vectorToNullArray(_ARGV, argvA);

argvA has some random value; argvA有一些随机值; passing it to vectorToNullArray results in undefined behavior.将它传递给vectorToNullArray导致未定义的行为。

The code doesn't allocate the array itself, but assigns values to it.代码不会分配数组本身,而是为其分配值。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM