Я спросил Google и провел некоторое исследование по StackOverflow. Мой вопрос заключается в том, что, когда я вхожу в 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
Как видите, я получаю разные результаты при разных казнях. Первая строка вывода соответствует адресу выделенной памяти, что должно происходить в куче — если им каждый раз назначаются разные адреса, это мне как-то логично. Однако даже когда я печатаю адреса локальных переменных — в соответствии со второй строкой — результаты все равно разные.
На первый взгляд, я думал, что это потому, что программа печатает адрес физической памяти, но этот пост, Виртуальная память или физическая память, опровергает мою первоначальную мысль Есть ли какая-то причина, по которой выполнение программ «одинаково», без потоков, ввода пользователя и т. Д., Что по-прежнему есть выделения памяти с разными адресами?
Среда тестирования:
При размещении в куче (используя new
оператор или malloc()
и друзья), ваша программа должна попросить ОС выделить вашу кучу памяти. Множество закулисных вещей происходит в диспетчере памяти ОС (детали реализации которого в основном выше моего уровня оплаты: сборка мусора, консолидация исправленной памяти и т. Д.), И это хорошая вещь не думать об этом.
Локальные переменные размещаются в стеке. Традиционно распределение стека повторяется, но в последние годы ситуация изменилась.
Рандомизация размещения адресного пространства (ASR) — сравнительно недавнее нововведение в управлении памятью ОС, которое намеренно делает адреса памяти при распределении стека (например, те, которые вы наблюдали) максимально недетерминированными во время выполнения. Это функция безопасности: это не позволяет плохим субъектам использовать переполнения буфера динамической памяти, потому что, если реализация ASLR достаточно энтропийна, кто знает, что будет в конце переполненного буфера?
Платой за эту и другие функции управления памятью является контроль. Ставки на адреса распределений на современной (не встроенной) платформе похожи на игру в Powerball: возможно, забавное отвлечение, но не осуществимый план на будущее. Если ваш код работает на платформе AVR-ISA или что-то подобное, возможно, шансы достаточно близки к Блэкджеку, так что кто-то может быть соблазн играть, чтобы выиграть (так сказать).
В любом случае, лично я не азартный человек — как я часто говорю, джентльмены предпочитают распределение стеков. Но именно поэтому вы получаете эти результаты.
Благодаря @ T.C. за ссылку и @SergeyA за предложение.
Других решений пока нет …