程序
#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)所示。如果它到达数据段,则发生冲突。 如果它发生,则没有更多的空间来分配主函数。因此,它会出现分段错误错误。所以使用上面的程序我实验它。 在该程序中,全局变量的地址是&#39; a&#39;是&#34; 0x804a014&#34;。每次调用main时,局部变量&#34; i&#34;得到宣布。所以我 期望,在分段错误之前,i的地址几乎要解决&#39; a&#39;。但是,这两个地址都非常不同。那么这里发生了什么。
为什么地址为&#39; a&#39;和&#39;我&#39;在分段错误错误时不在相同范围内。那么,如何交叉检查是否 main达到堆栈大小并且溢出?
答案 0 :(得分:1)
您的架构是概念模型或可能的实现。但是,例如,多线程程序每个线程有一个堆栈和一个堆,这不适合您的简化模式。
所需要的只是系统允许递归,这意味着函数的每次新调用都会获得局部变量的私有副本。剩下的只是依赖于实现。
最近的系统使用页面分配,并且流程通常会获得一组页面段,但它们不一定是连续的,并且您可以在它们之间有 hole ,其中任何访问都将获得SIGSEGV(段)违反)
TL / DR:你的程序更有可能得到一个SIGSEGV信号,而不是动态变量的地址到达静态地址 - 你应该找到一个旧的MS / DOS框来展示这种行为......
答案 1 :(得分:0)
&#39;一个&#39;是一个全局变量,它不会在堆栈中。这将在数据部分 - 即初始化的bss
&#39;我&#39;是一个局部变量,将存储在堆栈中。
这些是完全不同的部分,因此存在差异。
答案 2 :(得分:0)
当您编写 变量“i”声明 时,您正在编写正确的内容,但该变量未声明为全局a
。
i
是堆栈堆栈,堆栈有自己的大小。
ulimit
可以更改此限制。
您要查看的内容,全局变量的地址分配与本地变量之间的冲突是不可能的。
答案 3 :(得分:0)
你拥有的记忆模型是一个巨大的过度简化,这对于开始向学生讲授记忆基础知识是有用的,不要在开始时用细节来压倒他们。就像我们开始添加自然数字的数学教育一样。这是一个很好的基础,但如果你只是用它来理解现实,它就不会让你走得太远。
此模型至少在25 - 30年内不准确,不能用于预测实际的程序行为。堆和堆栈之间可能存在数十个(如果不是数千个)其他内存映射(共享库,大型malloc,mmap文件等)。 “堆”的概念是非常有问题的,因为通常它只不过是地址空间中任何地方的匿名内存的所有动态分配的总和,这是操作系统事先不知道的。
您的示例中发生的是您遇到堆栈资源限制(请参阅ulimit -s
)。