据我了解,调用时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)
从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::string
s可能包含\0
字符作为字符串数据的一部分,而不是作为终止符。
附带说明一下,该execv
调用将立即用新的调用进程替换调用进程。这意味着 C++ 析构函数不会被调用。对于std::string
、std::vector
和任何其他动态内存,这并不重要 - 所有分配的内存都会自动回收,因此不会泄漏。然而,其他副作用不会发生,也std::fstream
不会关闭文件等。一般来说,这并不重要,因为具有严重副作用的析构函数是糟糕的设计实践,但这是需要注意的事情。