11

Program

#include<stdio.h>
int a=10;
void main()
{
    int i=0;
    printf("global = %p, local = %p\n",&a,&i);
    main();
}

Output

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$

The above program gets segmentation fault Error. Because, the main gets call itself recursively. The following is the memory allocation to a C program.

memory allocation

          __________________                        __________________  
          |                |                        |                | 
          |      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)

So, I expect which is showed like in figure(b), the main call recursively. If it reaches the data segment, the collision occurs. If it occurs, there is no more space to allocate for main function. So, it gets segmentation fault error. So using the above program I experiment it. On that program, the address of global variable 'a' is "0x804a014". Each time main is called, the local variable "i" gets declared. So, I expect, before the segmentation fault, the address of i is nearly to address of 'a'. But, both the address are very different. So what's here going on.

Why the address of 'a' and 'i' is not in the same range at the time of segmentation fault error. So, how to cross check whether the main reaches the stack size and gets overflowed ?

mohangraj
  • 9,842
  • 19
  • 59
  • 94
  • 5
    pause the program, and have a look at `/proc/pid/maps` - there are other things in there, such as libraries. Plus there's an actual limit on the stack size (ulimit) – Anya Shenanigans Sep 30 '15 at 11:05
  • Could one print the addresses of objects from libraries? Say, &stdin? Or stdin? – Peter - Reinstate Monica Sep 30 '15 at 11:07
  • @Petesh This is the stack size: bf99c000-bfa39000 rw-p 00000000 00:00 0 [stack] – mohangraj Sep 30 '15 at 11:10
  • 6
    @mohan Your stack size is probably limited by `ulimit`, which is (typically) 8MB. Even on a 32bit system, you will *never* get the stack to overlap with the data segment in that case; even if there wasn't a bunch of libraries between them. I'm trying to guide you to understanding that an address map of a real process is different from the simple one you've shown. – Anya Shenanigans Sep 30 '15 at 11:17
  • So, stack size is fixed. It doesn't gets grow upto data segment. Is it right? – mohangraj Sep 30 '15 at 11:22
  • 1
    Try something like "ulimit -s 65000000 ; ./a.out" and it will last longer. – ysdx Sep 30 '15 at 11:26
  • Side note - calling `main` is undefined behaviour, so your compiler is entitled to do whatever it likes with this... – Toby Speight Sep 30 '15 at 11:55
  • This is the first time i see main() function called recursively! isn't that dangerous?! – machine_1 Sep 30 '15 at 12:29
  • @Petesh Like stack limt, is there any way to find the heap limit – mohangraj Oct 01 '15 at 09:09
  • 1
    @TobySpeight: Calling main is explicitely forbidden in C++ *3.6.1 Main function [basic.start.main] §3: The function main shall not be used within a program*, but I could not find equivalent in C specifications, so it looks like it should be allowed - even if highly uncommon... – Serge Ballesta Oct 01 '15 at 09:11
  • The closest equivalent is [`RLIMIT_DATA`](http://man7.org/linux/man-pages/man2/getrlimit.2.html); which is reported in ulimit as the `Maximum size of a process’s data segment`. – Anya Shenanigans Oct 01 '15 at 09:17

4 Answers4

1

Your schema is a conceptual model or a possible implementation. But for example a multithreaded program will have one stack per thread and one single heap, which does not really fit in your simplified schema.

All what is required is that the system allows recursion, meaning that each new invocation of a functions gets a private copy of local variables. All what remains is implementation dependant.

Recent system use page allocation, and a process generally gets a set of page segments, but they are not necessarily consecutive, and you can have holes between them where any access will get a SIGSEGV (segment violation)

TL/DR: you program will more likely get a SIGSEGV signal than the address of the dynamic variable reaching the address of static one - you should find an old MS/DOS box to exhibit such behaviour...

Serge Ballesta
  • 143,923
  • 11
  • 122
  • 252
0

'a' is a global variable and it will not be in stack. This will be in data section - i.e., initialized bss

'i' is a local variable and will be stored in the stack.

These are entirely different sections and hence the difference.

Please refer Global memory management in C++ in stack or heap?

Community
  • 1
  • 1
hazzelnuttie
  • 1,403
  • 1
  • 12
  • 22
0

When you wrote variable "i" gets declared, you are writing something correct, but the variable is not declared as the global a.

i is stack allocated, and stack has its own size.

ulimit can change that limit.

What you are trying to see, collision between address allocation of a global variable and a local variable, is not possible.

LPs
  • 16,045
  • 8
  • 30
  • 61
0

The memory model you have is a huge oversimplification that's only useful to start teaching the basics of memory to students to not overwhelm them with details in the beginning. Just like we start math education with addition of natural numbers. It's a good fundament but it won't get you far if you use just that to understand reality.

This model has not been accurate for at least 25-30 years and can't be used to make predictions about actual program behavior. There can be dozens, if not thousands, of other memory mappings between the heap and stack (shared libraries, large mallocs, mmap of files, etc.). The concept of "heap" is highly problematic because often it's not much more than the sum of all dynamic allocations of anonymous memory anywhere in the address space for purposes that the operating system didn't know beforehand.

What's happening in your example is that you run into the stack resource limit (see ulimit -s).

Art
  • 19,807
  • 1
  • 34
  • 60