这是“APUE”第 8 章(练习 8.2,第 2 版)中的练习。全部说明是:
回忆一下图 7.6 中典型的内存排列。因为每个函数调用对应的栈帧通常都存储在栈中,并且因为在 vfork 之后子进程在父进程的地址空间中运行,如果对 vfork 的调用来自除 main 之外的函数并且子进程执行了会发生什么情况在 vfork 之后从这个函数返回?编写一个测试程序来验证这一点,并画出正在发生的事情。
在我的程序中:
static void f1(void), f2(void);
int main(void) {
printf("main address: %d\n", main);
f1();
f2();
_exit(0);
}
static void f1(void) {
printf("f1 address: %d\n", f1);
pid_t pid;
if ((pid = vfork()) < 0)
err_sys("vfork error");
}
static void f2(void) {
printf("f2 address: %d\n", f2);
char buf[1000];
int i;
for (i = 0; i < sizeof(buf); ++i)
buf[i] = 0;
}
我运行程序,输出为:
main address: 4196560
f1 address: 4196604
f2 address: 4196663
f1 address: 4196604
[1] 12929 segmentation fault ./a.out
我对输出感到困惑。
- print
f1 address: xxx
,我们调用 vfork() ,子进程首先运行。 - print
f2 address: xxx
,然后子进程调用 _exit(0)。 - 主进程从 f1() 返回,f1 的堆栈帧被 f2 更改,可能导致分段错误。
但是为什么要打印f1 address: 4196604
两次,为什么 f1 和 f2 的地址不一样呢?