Подтвердить что ты не робот

Распределение памяти для программы C

Программа

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

Выход

[email protected]:~/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)
[email protected]:~/Advanced_Unix/Chapter7$

Вышеупомянутая программа получает ошибку сегментации Error. Потому что главный рекурсивно получает вызов. Ниже приведена память выделение для программы 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), главный вызов рекурсивно. Если он достигает сегмента данных, происходит столкновение. Если это происходит, больше нет места для выделения для основной функции. Таким образом, он получает ошибку ошибки сегментации. Поэтому, используя описанную выше программу, я ее экспериментирую. В этой программе адрес глобальной переменной "a" равен "0x804a014". Каждый раз, когда вызывается main, объявляется локальная переменная i. Так что я ожидайте, перед ошибкой сегментации адрес я близок к адресу 'a'. Но, оба адреса очень разные. Так что здесь происходит.

Почему адрес "a" и "i" находится не в том же диапазоне во время ошибки ошибки сегментации. Итак, как перекрестно проверить, main достигает размера стека и переполняется?

4b9b3361

Ответ 1

Ваша схема представляет собой концептуальную модель или возможную реализацию. Но, например, многопоточная программа будет иметь один стек для потока и одну кучу, которая не очень подходит для вашей упрощенной схемы.

Все, что требуется, - это то, что система позволяет рекурсию, что означает, что каждый новый вызов функций получает частную копию локальных переменных. Все, что остается, зависит от реализации.

Недавнее распределение страниц в системе, и процесс обычно получает набор сегментов страницы, но они не обязательно последовательны, и между ними могут быть отверстия, где любой доступ будет получать SIGSEGV (нарушение сегмента)

TL/DR: вы, скорее всего, получите сигнал SIGSEGV, чем адрес динамической переменной, достигающей адреса статического, - вы должны найти старый ящик MS/DOS для проявления такого поведения...

Ответ 2

'a' - глобальная переменная, и она не будет в стеке. Это будет в разделе данных, то есть инициализированном bss

'i' является локальной переменной и будет храниться в стеке.

Это совершенно разные разделы и, следовательно, разница.

Пожалуйста, обратитесь Глобальное управление памятью в С++ в стеке или куче?

Ответ 3

Когда вы написали переменную "i" объявили, вы пишете что-то правильное, но переменная не объявляется глобальным a.

i выделяется стек, а стек имеет свой собственный размер.

ulimit может изменить этот предел.

То, что вы пытаетесь увидеть, столкновение между распределением адресов глобальной переменной и локальной переменной, невозможно.

Ответ 4

Модель памяти, которую вы имеете, представляет собой огромное упрощение, которое полезно только для того, чтобы начать преподавать основы памяти ученикам, чтобы не перегружать их деталями в начале. Так же, как мы начинаем математическое образование с добавлением натуральных чисел. Это хороший фундамент, но он не заставит вас далеко ходить, если вы используете именно это, чтобы понять реальность.

Эта модель не была точной не менее 25-30 лет и не может использоваться для прогнозирования фактического поведения программы. Могут быть десятки, если не тысячи, других сопоставлений памяти между кучей и стеком (разделяемые библиотеки, большие mallocs, mmap файлов и т.д.). Понятие "куча" очень проблематично, потому что часто это не намного больше суммы всех динамических распределений анонимной памяти в любом месте адресного пространства для целей, которые операционная система не знала заранее.

Что происходит в вашем примере, так это то, что вы запускаете ограничение на ресурс стека (см. ulimit -s).