我正在研究另一个StackOverflow question的内容,我认为现在是了解unix系统调用知识的好时机。
在尝试使用execvp
(没有叉子)的时候,我遇到了让我困惑的事情
我写了4个测试程序
#include <stdio.h>
int main() {
//printf("Doge\n");
execvp("ls");
printf("Foo\n");
return 0;
}
该程序按预期工作,目录的内容被打印,Foo
打印语句不是
但是,当我取消注释第一个print语句并将程序设为此
时#include <stdio.h>
int main() {
printf("Doge\n");
execvp("ls");
printf("Foo\n");
return 0;
}
execvp
返回-1
,并发出两个打印语句。为什么呢?
我依稀记得在试用大学的unix系统调用时必须使用unistd.h
。
所以我把它包括在内,但不是execvp
有一个不同的签名,它需要更多的args而不仅仅是程序的名称。所以我做了这个
#include <stdio.h>
#include <unistd.h>
int main() {
printf("Doge\n");
char *const parmList[] = {"ls", NULL};
execvp("ls", parmList);
printf("Foo\n");
return 0;
}
这很有效。这让我很困惑。为什么exec在第一个程序中工作? 我还使用This作为系统调用的引用。
最后我写了
#include <stdio.h>
//#include <unistd.h>
int main() {
printf("Doge\n");
char *const parmList[] = {"ls", NULL};
execvp("ls", parmList);
printf("Foo\n");
return 0;
}
哪个也按预期工作。
有人能解释一下发生了什么吗?
答案 0 :(得分:3)
使用此代码段
#include <stdio.h>
int main() {
execvp("ls");
printf("Foo\n");
return 0;
}
您正在调用未定义的行为。您没有提供execvp
的原型,它需要一个参数列表(以空值终止)作为第二个参数。
在没有任何警告选项的情况下使用gcc
以隐式声明的方式静默使用execvp
,并且不会检查参数。它只是调用函数。然后该函数查找第二个参数并遇到...调用堆栈剩余的内容(或寄存器,具体取决于调用约定),这就是为什么先前的printf
调用可以改变行为。< / p>
使用gcc -Wall
会发出以下警告:
test.c:5:9: warning: implicit declaration of function 'execvp' [-Wimplicit-function-declaration]
execvp("ls");
包括正确的包含(#include <unistd.h>
)会导致:
test.c:6:9: error: too few arguments to function 'execvp'
execvp("ls");
^~~~~~
这就是为什么你有奇怪的行为。别再看了。使用带有2个参数的execvp
,句点。在您的情况下&#34;计划3&#34;是可行的方法,并始终将警告级别设置为最大值(gcc
和clang
:-Wall -Wextra -pedantic -Werror
)