【发布时间】:2015-12-28 03:23:11
【问题描述】:
计划
#include<stdio.h>
int a=10;
void main()
{
int i=0;
printf("global = %p, local = %p\n",&a,&i);
main();
}
输出
mohanraj@ltsp63:~/Advanced_Unix/Chapter7$ ./a.out
global = 0x804a014, local = 0xbfff983c
global = 0x804a014, local = 0xbfff980c
.
.
.
global = 0x804a014, local = 0xbf7fac9c
global = 0x804a014, local = 0xbf7fac6c
global = 0x804a014, local = 0xbf7fac3c
Segmentation fault (core dumped)
mohanraj@ltsp63:~/Advanced_Unix/Chapter7$
上述程序出现分段错误错误。因为, main 递归地调用自己。以下是回忆 分配给 C 程序。
内存分配
__________________ __________________
| | | |
| stack | | Main |
| ↓ | |----------------|
------------------ | Main |
| | |----------------|
| <Un Allocated| | Main |
| space> | |----------------|
------------------ | Main |
| | |----------------|
| ↑ | | Main |
| Heap | |----------------|
| | | Main |
| | |----------------|
__________________ |////////////////| ---> Collision occurs. So, Segmentation fault Occurs.
| | |________________|
| data | | data |
__________________ |________________|
| text | | text |
__________________ |________________|
Figure(a) Figure(b)
所以,我希望如图(b)所示,主要调用递归。如果它到达数据段,就会发生冲突。 如果发生,则没有更多空间可分配给 main 函数。因此,它会出现分段错误错误。所以我用上面的程序做实验。 在该程序中,全局变量“a”的地址是“0x804a014”。每次调用 main 时,都会声明局部变量“i”。所以我 预计,在分段错误之前,i 的地址几乎是“a”的地址。但是,这两个地址是非常不同的。那么这里发生了什么。
为什么segment fault错误时'a'和'i'的地址不在同一范围内。那么,如何交叉检查是否 main 达到堆栈大小并溢出?
【问题讨论】:
-
暂停程序,看看
/proc/pid/maps——里面还有其他东西,比如库。另外,堆栈大小有一个实际限制(ulimit) -
可以打印库中对象的地址吗?说,&stdin?还是标准输入?
-
@mohan 您的堆栈大小可能受到
ulimit的限制,即(通常)8MB。即使在 32 位系统上,在这种情况下,您也永远不会让堆栈与数据段重叠;即使他们之间没有一堆图书馆。我试图引导您了解真实流程的地址映射与您展示的简单流程不同。 -
尝试类似“ulimit -s 65000000 ; ./a.out”,它会持续更长时间。
-
@TobySpeight:C++ 中明确禁止调用 main 3.6.1 Main 函数 [basic.start.main] §3:函数 main 不得在程序中使用 ,但我在 C 规范中找不到等效项,所以看起来应该允许它 - 即使非常罕见......