简体   繁体   中英

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 **.

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. 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.

EDIT 2: working solution

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:

    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

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.

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. Perhaps you can do something like below, then pass the result's .data() value to 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.

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; passing it to vectorToNullArray results in undefined behavior.

The code doesn't allocate the array itself, but assigns values to it.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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