传递给 exec*() 系列函数的参数中的内存会发生什么情况?

Wil*_*mKF 6 c++ memory exec

据我了解,调用时exec*()旧进程的内存完全被新程序替换。但是,像argv这样的参数的内存呢?如果我有这样的代码,使用 C++ 数据结构中的内存是否安全,例如std::string这些数据结构是否会消失、损坏argv

#include <unistd.h>
#include <string>
#include <string.h>
#include <vector>
#include <iostream>

void
execExample(const std::vector<std::string> &arguments)
{
  char **argv = new char *[arguments.size() + 2];
  char *path = "/path/to/my/executable";
  unsigned int idx = 0;

  argv[idx] = path;

  for (; ++idx < arguments.size() + 1; ) {
    argv[idx] = const_cast<char *>(arguments[idx - 1].c_str());
  }

  argv[idx] = 0;

  execv(path, argv); // Does not return if successful.

  std::cerr << "exec failed: " << strerror(errno) << ".\n";
}
Run Code Online (Sandbox Code Playgroud)

Luc*_*iel 4

execv手册页

execv()、execvp() 和 execvpe() 函数提供指向以 null 结尾的字符串的指针数组,这些字符串表示新程序可用的参数列表。按照惯例,第一个参数应该指向与正在执行的文件关联的文件名。指针数组必须以 NULL 指针终止。[强调已添加]

因此,您提供了一个以 null 结尾的C字符串的数组。手册页没有明确说明内存发生了什么,但大概字符串被复制到新进程,就像通过strcpy, 复制到新进程一样,并且新指针被提供给main新进程的 。因为execv不可能知道有关这些字符串的任何上下文(它们是静态的吗?本地的?malloc'd?),所以在我看来,指针数组不太可能被浅层复制到新进程

为了解决您的确切问题,这意味着几乎任何以 null 结尾的源char*(包括std::string、 viastr.c_str()str.data())都可以用作传递给 的数组的一部分execv。值得注意的是,在 C++11 之前,std::strings不需要以 null 结尾,只要成员返回指向以 null 结尾的字符串的指针即可c_str我不知道任何std::string不是以 null 终止的实现,但值得注意的是,与 c-strings 不同,std::strings可能包含\0字符作为字符串数据的一部分,而不是作为终止符。

附带说明一下,该execv调用将立即用新的调用进程替换调用进程。这意味着 C++ 析构函数不会被调用。对于std::stringstd::vector和任何其他动态内存,这并不重要 - 所有分配的内存都会自动回收,因此不会泄漏。然而,其他副作用不会发生,也std::fstream不会关闭文件等。一般来说,这并不重要,因为具有严重副作用的析构函数是糟糕的设计实践,但这是需要注意的事情。