意外的fork行为
Unexpected fork behavior
我有一个无限期运行的程序。出于测试目的,我制作了一个包装程序,在指定的时间(通过命令行/终端参数指定)后杀死另一个。被分叉的程序要求传递给它两个具有相同名称的文件夹(我无法控制这一点),所以我简单地将相同的参数传递给它两次,如下所示:
pid_t pid = fork();
if(pid == 0)
{
//build the execution string
char* test[2];
test[0] = argv[2];
test[1] = argv[2];
test[2] = NULL;
cout << "test[0] is " << test[0] << endl;
cout << "test[1] is " << test[1] << endl;
cout << "argv[1] is " << argv[1] << endl;
execvp(argv[1],test);
}
问题是在argv[1]中传递的程序保持分段错误。如果我通过终端调用它,它运行起来没有问题。在这两种情况下,我传递的是同一个文件夹。谁能告诉我为什么这对执行不奏效?
我应该提到一个同事也在他的电脑上运行了它,第一次它会正常运行,但每次之后,它都会出现故障。
编辑:我已经添加了一个空项来测试,但是,这并没有解决这个问题。
命令的格式是:
<executable> <wrapped prog> <folder> <duration>
相对路径为:
Intel/debug/Tester.exe <program> test 10
如果数组的长度是静态的,那么最好使用
execlp
execlp(argv[1], argv[1], argv[2], argv[2], (char*)0);
对于execvp
,数组应该以可执行文件名开始,以NULL
结束。
execvp
char* args[] = { argv[1], argv[2], argv[2], NULL };
execvp(argv[1], args);
<标题> runWithTimeout h1> 任何情况下,如果你想要的只是一个简单的包装器,运行一个带有超时的子进程,那么只要你愿意从timeout参数开始,你的程序就可以非常简单和通用:
/*runWithTimeout.c
compile with: make runWithTimeout
run with: ./runWithTimeout seconds program arguments...
*/
#include <stdlib.h>
#include <assert.h>
#include <unistd.h>
int main(int argc, char** argv)
{
assert(argc >= 1+2);
int pid, status = 1;
if((pid = fork()) == 0) {
alarm(atoi(argv[1]));
execvp(argv[2], argv + 2);
/*^the child ends here if execvp succeeds,
otherwise fall-through and return the default error status of 1
(once in child (which has no one to wait on) and
then in the parent (which gets the status from the child))*/
perror("Couldn't exec");
}else if(pid < 0){ perror("Couldn't fork"); };
wait(&status);
return status;
}
标题>作为参数传递的数组应该以空结束。例如:
char *test[3]={0};
...
您可以打开核心转储(确保完成后关闭它们)ulimit -c unlimited
。在运行主进程之前运行它。(我希望在fork中运行它,尽管你可能可以。)
当你的程序崩溃时,这将产生一个核心转储,你可以用gdb检查。
对于核心文件的帮助,你可以直接谷歌它们。
除此之外。您可以编写一个脚本来启动文件。您可以使用该脚本记录内容。
你想:
char* test[3];
test[0] = argv[2];
test[1] = argv[2];
test[2] = NULL;
您需要一个NULL参数来标记参数列表的结束
给定规格:
命令的格式是:
<executable> <wrapped prog> <folder> <duration>
相对路径为:
Intel/debug/Tester.exe <program> test 10
也:
然后,假设您已经检查了包装器传递了4个参数,您需要的代码是:被分叉的程序需要传递给它两个同名的文件夹…
pid_t pid = fork();
if (pid == 0)
{
//build the execution string
char *test[4]; // Note the size!
test[0] = argv[1]; // Program name: argv[0] in exec'd process
test[1] = argv[2]; // Directory name: argv[1] …
test[2] = argv[2]; // Directory name: argv[2] …
test[3] = NULL; // Null terminator
cout << "test[0] is " << test[0] << endl;
cout << "test[1] is " << test[1] << endl;
cout << "test[2] is " << test[2] << endl;
execvp(test[0], test);
cerr << "Failed to exec '" << test[0] << "': " << strerror(errno) << endl;
exit(1); // Or throw an exception, or …
}
对于argv
中的参数数组,除了使用习惯用法execvp(argv[0], argv)
之外,很少(但不是永远)有理由调用execvp()
。
注意,这段代码确保控制流不会从应该表示子节点的语句块中转义。让子进程在之后继续,通常实际上认为它是父进程,这会导致混乱。始终确保子进程执行或退出。(这是夸大其词——是的;但这个想法背后也有很大一部分事实。)此外,由于这是c++,您可能需要考虑如何结束c++代码?这使生活变得复杂。关键的是,如果子进程执行失败,它不会像父进程那样继续。
- 理解boost::asio-async_read在无需读取内容时的行为
- 模板-模板参数推导:三个不同的编译器三种不同的行为
- arr[-1]在c++中的奇怪行为
- 继承期间显示未知行为的子类
- 如何在c++中使用引用实现类似python的行为
- G锁定铸造到基础上会释放模拟行为
- 在C++中对T*类型执行std::move的意外行为
- std::当在256字节边界上写入整数时,流的奇怪行为
- 不知道某个东西是否被忽略会引入未定义的行为吗
- 奇怪的构造函数行为
- 重载运算符new[]的行为取决于析构函数
- 不同语言中相同代码的不同行为
- 处理除以零会导致<csignal>意外行为
- 试图理解类对象的行为
- c++11评估顺序(未定义的行为)
- 从结构寻址时,MMAP变量的行为很奇怪
- 我可以做些什么来消除或最小化这种将提供相同功能和行为的代码重复
- 读取文件时运行时的未知行为
- 意外的fork行为
- CreateThread的行为似乎类似于fork()