【发布时间】:2015-04-05 05:16:41
【问题描述】:
这是“APUE”第 8 章中的练习(练习 8.2,第 2 版)。全部描述为:
回忆一下图 7.6 中典型的内存排列方式。因为堆栈帧 每个函数调用对应的通常都存放在堆栈中,并且因为经过一个 vfork 子进程在父进程的地址空间中运行,如果调用 vfork 会发生什么 来自除 main 之外的函数,并且孩子在 叉子?编写一个测试程序来验证这一点,并画出正在发生的事情。
在我的程序中:
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
我对输出感到困惑。
- 打印
f1 address: xxx,我们调用vfork(),子进程先运行。 - 打印
f2 address: xxx,然后子进程调用_exit(0)。 - 主进程从f1()返回,f1的栈帧被f2改变了,可能导致segmentation fault。
但是为什么要打印两次f1 address: 4196604,为什么f1和f2的地址不一样呢?
【问题讨论】:
-
buf未初始化,因此strlen(buf)是未定义的行为(可能是段错误的原因)。这是故意的吗? -
vfork 是你平台上 fork() 的别名吗?
-
@rici sizeof(buf) 是一样的
-
它甚至不相似。 strlen 对字节进行计数,直到找到 0。
-
@rici 你是对的,我已经使用 sizeof() 改变了 strlen()。