fork 和 execve 分段错误
Fork and execve segmentation fault
我的程序应该使用 fork 和 exec 系统调用。 exec 应该更改子进程,使其将另一个命令作为参数并执行
那个命令。例如,要显示当天的消息:
./myexec cat /etc/motd
这是我当前的代码
extern char **environ; /* environment info */
main(int argc, char **argv) {
/* argc -- number of arguments */
/* argv -- an array of strings */
char *argvNew[argc + 1];
int pid;
for(int i=0; i<argc; i++){
argvNew[i] = argv[i];
}
argvNew[argc + 1] = NULL;
printf("After For: %s\n",argvNew[0]);
printf("After For: %s\n",argvNew[1]);
printf("After For: %s\n",argvNew[2]);
printf("After For: %s\n",argvNew[3]);
if ((pid = fork()) < 0) {
fprintf(stderr, "Fork error%sstrerror\n", strerror(errno));
exit(1);
}
else if (pid == 0) {
/* child process */
if (execve(argvNew[0], argvNew, environ) < 0) {
fprintf(stderr, "Execve error%d %s\n",errno,strerror(errno));
exit(1);
}
}
else {
/* parent */
wait(0); /* wait for the child to finish */
}
}
运行./myexecv cat etc/motd
之后没有任何反应;只是打印语句。有什么建议吗?
显示的代码中存在多个错误。
for(int i=0; i<argc; i++){
argvNew[i] = argv[i];
}
argvNew[argc+1] = NULL;
从表面上看,NULL 分配是错误的,并且会导致未定义的行为,因为 argvNew
被声明为
char *argvNew[argc + 1];
因此数组包含值 argvNew[0]
到 argvNew[argc]
,并且 argvNew[argc+1]=NULL;
运行 超出数组末尾,这会导致未定义的行为。这显然应该是
argvNew[argc] = NULL;
但即使那样也是错误的,因为:
execve(argvNew[0], argvNew, environ);
argvNew[0]
是从 argv[0]
复制而来的,这是正在执行的程序的名称。这将在子进程中分叉 运行 同一个程序。
你最终会用叉子轰炸自己。如果这是一个共享服务器,你会让系统管理员非常非常生气。
您需要从等式中删除 argv[0]
,然后仅复制 argv[1]
,等等。正确的循环和复制是:
int pid;
char *argvNew[argc];
for(int i=1; i<argc; i++){
argvNew[i-1] = argv[i];
}
argvNew[argc-1] = NULL;
execve()
的调用参数要求第一个参数是要执行的文件名。不幸的是,您传递给它的 argvNew[0]
与 argv[0]
的值相同。这意味着您调用并再次调用您自己的程序,而不是脚本。您需要将参数移动一位:
...
for(int i=1; i<argc; i++){
argvNew[i-1] = argv[i];
}
argvNew[argc-1] = NULL;
...
我的程序应该使用 fork 和 exec 系统调用。 exec 应该更改子进程,使其将另一个命令作为参数并执行 那个命令。例如,要显示当天的消息:
./myexec cat /etc/motd
这是我当前的代码
extern char **environ; /* environment info */
main(int argc, char **argv) {
/* argc -- number of arguments */
/* argv -- an array of strings */
char *argvNew[argc + 1];
int pid;
for(int i=0; i<argc; i++){
argvNew[i] = argv[i];
}
argvNew[argc + 1] = NULL;
printf("After For: %s\n",argvNew[0]);
printf("After For: %s\n",argvNew[1]);
printf("After For: %s\n",argvNew[2]);
printf("After For: %s\n",argvNew[3]);
if ((pid = fork()) < 0) {
fprintf(stderr, "Fork error%sstrerror\n", strerror(errno));
exit(1);
}
else if (pid == 0) {
/* child process */
if (execve(argvNew[0], argvNew, environ) < 0) {
fprintf(stderr, "Execve error%d %s\n",errno,strerror(errno));
exit(1);
}
}
else {
/* parent */
wait(0); /* wait for the child to finish */
}
}
运行./myexecv cat etc/motd
之后没有任何反应;只是打印语句。有什么建议吗?
显示的代码中存在多个错误。
for(int i=0; i<argc; i++){
argvNew[i] = argv[i];
}
argvNew[argc+1] = NULL;
从表面上看,NULL 分配是错误的,并且会导致未定义的行为,因为 argvNew
被声明为
char *argvNew[argc + 1];
因此数组包含值 argvNew[0]
到 argvNew[argc]
,并且 argvNew[argc+1]=NULL;
运行 超出数组末尾,这会导致未定义的行为。这显然应该是
argvNew[argc] = NULL;
但即使那样也是错误的,因为:
execve(argvNew[0], argvNew, environ);
argvNew[0]
是从 argv[0]
复制而来的,这是正在执行的程序的名称。这将在子进程中分叉 运行 同一个程序。
你最终会用叉子轰炸自己。如果这是一个共享服务器,你会让系统管理员非常非常生气。
您需要从等式中删除 argv[0]
,然后仅复制 argv[1]
,等等。正确的循环和复制是:
int pid;
char *argvNew[argc];
for(int i=1; i<argc; i++){
argvNew[i-1] = argv[i];
}
argvNew[argc-1] = NULL;
execve()
的调用参数要求第一个参数是要执行的文件名。不幸的是,您传递给它的 argvNew[0]
与 argv[0]
的值相同。这意味着您调用并再次调用您自己的程序,而不是脚本。您需要将参数移动一位:
...
for(int i=1; i<argc; i++){
argvNew[i-1] = argv[i];
}
argvNew[argc-1] = NULL;
...