Изменение адреса кучи между запусками, в то время как другие адреса сохраняются

Куча меня беспокоит, потому что я не понимаю, кто ее создает, кто ее поддерживает и кто решает, где она должна быть ... Этот тест показывает часть моей головоломки:

Исходный код:

#include <malloc.h>
#include <stdio.h>

int a;
int b = 5;

int * getMeAPointer() {
    int * e = malloc(4);
    *e = 5;
    return e;
}


void main() {
    a = 5;
    int c = 5;
    int * d = (int *) 0x405554;
    *d = 5;
    int * e = getMeAPointer();
    printf("Address of a located in .bss is %x\n", &a);
    printf("Address of b located in .data is %x\n", &b);
    printf("Address of c located in stack is %x\n", &c);
    printf("Address of d located in stack is %x\n", &d);
    printf("Address of *d located absolutely is %x\n", d);
    printf("Address of e located in stack is %x\n", &e);
    printf("Address of *e located on heap is %x\n", e);
    printf("Address of getMeAPointer() located in .text is %x\n", getMeAPointer);
    free(e);
}

Примеры распечаток:

Address of a located in .bss is 0x405068
Address of b located in .data is 0x402000
Address of c located in stack is 0x22ff1c
Address of d located in stack is 0x22ff18
Address of *d located absolutely is 0x405554
Address of e located in stack is 0x22ff14
Address of *e located on heap is 0x541738
Address of getMeAPointer() located in .text is 0x4013b0

Address of a located in .bss is 0x405068
Address of b located in .data is 0x402000
Address of c located in stack is 0x22ff1c
Address of d located in stack is 0x22ff18
Address of *d located absolutely is 0x405554
Address of e located in stack is 0x22ff14
Address of *e located on heap is 0x3a1738
Address of getMeAPointer() located in .text is 0x4013b0

Address of a located in .bss is 0x405068
Address of b located in .data is 0x402000
Address of c located in stack is 0x22ff1c
Address of d located in stack is 0x22ff18
Address of *d located absolutely is 0x405554
Address of e located in stack is 0x22ff14
Address of *e located on heap is 0x351738
Address of getMeAPointer() located in .text is 0x4013b0

....etc....

Теперь это мои проблемы:

  1. Почему движется куча, а не другие сегменты? Это на ОС Windows 7 с MinGW, и этот файл был скомпилирован с GCC без дополнительных флагов (я не верю, что это пример рандомизации макета адресного пространства).

  2. Кто решает, где должна быть куча? Я верю, что компоновщик резервирует место для кучи (я видел символы кучи в таблицах символов), но когда определен точный адрес, выполняется ли это во время выполнения самим RUNNABLE (код C) ПОСЛЕ загрузки или сделано компоновщиком /загрузчиком /динамическим компоновщиком во время ЗАГРУЗКИ программы прямо перед выполнением?

  3. Есть ли способ установить адрес кучи в ld? Я понял, что могу установить все сегменты, кроме стека (поскольку он встроен в ядро ​​ОС), но могу ли я установить адрес кучи?

  4. В моем понимании, куча на самом деле не является конструкцией на языке ассемблера, и у нас нет доступа к куче, если мы решаем просто программировать на ассемблере. Поэтому это конструкция C, но меня интересует, как это влияет на жизнь кучи (я имею в виду, что мы говорим о куче, как будто она находится на одном уровне с сегментами и стеком, но если это не так, то это должно дать ему много других условий) ... это правильно, и кто-нибудь может рассказать мне что-нибудь еще об этом?

Если честно, я целый день работал в Google, и я жажду ответов!

4 голоса | спросил fast-reflexes 9 MaramSun, 09 Mar 2014 01:26:31 +04002014-03-09T01:26:31+04:0001 2014, 01:26:31

2 ответа


0
  

Почему куча движется и ни один из других сегментов?

Потому что динамическое распределение памяти, ну, динамическое. Адрес, который вы получите от malloc(), зависит от где достаточно большой кусок свободной памяти можно найти в тот момент, когда ваша программа выполняется. Очевидно, что, поскольку существуют и другие программы, со временем это меняется.

  

Кто решает, где должна быть куча?

Разработчики вашей операционной системы.

  

Я верю [sic!], что компоновщик резервирует место для кучи

Редко. На большинстве реализаций, которые я видел, это все время выполнения. (Это не значит, что компоновщик не имеет к этому никакого отношения, но все же.)

  

Есть ли способ установить адрес кучи в ld?

Если это так, то это задокументировано . (Предполагая, что ld, на который вы ссылаетесь, является компоновщиком в вашей цепочке инструментов.)

  

[...] Я могу установить все сегменты, кроме стека (так как он встроен в ядро ​​ОС)

Я не думаю, что полностью понимаю, что вы говорите, но «стек» не «встроен в ядро». Обычно адрес стека либо статически жестко запрограммирован в исполняемом файле, либо на него ссылаются с помощью относительных инструкций.

  

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

Но да, вы делаете. Я не знаком с Windows, но в большинстве Unix-систем вы можете использовать brk() и /или sbrk() системные вызовы.

  

Следовательно, это конструкция C

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

ответил user3383733 9 MaramSun, 09 Mar 2014 01:37:02 +04002014-03-09T01:37:02+04:0001 2014, 01:37:02
0

Различные факторы будут влиять на то, где будет располагаться куча, т.е.

  • Базовый адрес приложения
  • Библиотеки, необходимые для приложения
  • Что операционная система выделяет приложению

Куча C - это (упрощенно) просто огромный блок памяти, который поддерживается средой выполнения приложения, поэтому эффективный адрес, который вы получаете при вызове malloc (), определяется этой средой выполнения. Время выполнения отличается между версиями компилятора и разных поставщиков. Блок памяти всей , который среда выполнения использует в качестве кучи, получается из операционной системы при запуске приложения. Здесь операционная система может возвращать новый адрес при каждом запуске приложения. Следовательно, адреса кучи непредсказуемы. Если ваше приложение начнет выделять и освобождать память во время выполнения, оно будет даже «более» случайным, потому что теперь среде выполнения необходимо находить свободные блоки между выделенными в данный момент блоками и так далее. Таким образом, если последовательность распределений /откреплений не будет одинаковой между запусками, вы получите совершенно разные адреса, даже если базовый адрес кучи одинаков.

ответил PMF 9 MaramSun, 09 Mar 2014 01:40:08 +04002014-03-09T01:40:08+04:0001 2014, 01:40:08

Похожие вопросы

Популярные теги

security × 330linux × 316macos × 2827 × 268performance × 244command-line × 241sql-server × 235joomla-3.x × 222java × 189c++ × 186windows × 180cisco × 168bash × 158c# × 142gmail × 139arduino-uno × 139javascript × 134ssh × 133seo × 132mysql × 132