Почему адреса локальных переменных могут отличаться каждый раз?
Я спросил Google и провел некоторое исследование по Stackru. Мой вопрос заключается в том, что, когда я вхожу в main()
функционировать в программе на C++ и объявлять самую первую переменную, почему адрес этой переменной может варьироваться в зависимости от выполнения? Пожалуйста, смотрите мой пример программы ниже:
#include <iostream>
int main() {
int *a = new int;
int *b = new int;
std::cout << "address: " << a << " " << b << std::endl;
std::cout << "address of locals: " << &a << " " << &b << std::endl;
return 0;
}
Результат по исполнению 1:
address: 0xa32010 0xa32030
address of locals: 0x7fff10de2cf0 0x7fff10de2cf8
Результат по исполнению 2:
address: 0x1668010 0x1668030
address of locals: 0x7ffc252ccd90 0x7ffc252ccd98
Результат по исполнению 3:
address: 0x10e0010 0x10e0030
address of locals: 0x7ffd3d2cf7f0 0x7ffd3d2cf7f8
Как видите, я получаю разные результаты при разных казнях. Первая строка вывода соответствует адресу выделенной памяти, что должно происходить в куче - если им каждый раз назначаются разные адреса, это мне как-то логично. Однако даже когда я печатаю адреса локальных переменных - в соответствии со второй строкой - результаты все равно разные.
На первый взгляд, я думал, что это потому, что программа печатает адрес физической памяти, но этот пост, Виртуальная память или Физическая память, опровергает мою первоначальную мысль. Есть ли какая-то причина, по которой выполнение программ "одинаково", без потоков, без ввода данных пользователем и т. Д., Что по-прежнему есть выделения памяти с разными адресами?
Среда тестирования:
- Linux 14.04
- Mac OS X 10.10
1 ответ
При размещении в куче (используя new
оператор или malloc()
и друзья), ваша программа должна попросить ОС выделить вашу кучу памяти. Множество закулисных вещей происходит в диспетчере памяти ОС (детали реализации которых в основном выше моего уровня оплаты: сборка мусора, консолидация исправленной памяти и т. Д.), И это хорошая вещь, о которой не нужно думать Это.
Локальные переменные размещаются в стеке. Традиционно, распределение стека будет повторяться, но это изменилось в последние годы. Рандомизация размещения адресного пространства (ASR) - сравнительно недавнее нововведение в управлении памятью ОС, которое намеренно делает адреса памяти в распределениях стека (например, те, которые вы наблюдали) максимально недетерминированными во время выполнения. Это функция безопасности: это не позволяет плохим акторам использовать переполнения буфера кучи, потому что, если реализация ASLR достаточно энтропийна, кто знает, что будет в конце переполненного буфера?
Платой за эту и другие функции управления памятью является контроль. Ставки на адреса распределений на современной (не встроенной) платформе похожи на игру в Powerball: возможно, это забавное отвлечение, но не осуществимый план на будущее. Если ваш код работает на платформе AVR-ISA или что-то подобное, возможно, шансы достаточно близки к Блэкджеку, так что кто-то может быть соблазн играть, чтобы выиграть (так сказать).
В любом случае, лично я не азартный человек - как я часто говорю, джентльмены предпочитают распределение стека. Но именно поэтому вы получаете эти результаты.
Спасибо @TC за ссылку и @SergeyA за предложение.