Почему печатные адреса памяти в Rust представляют собой сочетание 40-битных и 48-битных адресов? - PullRequest
0 голосов
/ 07 апреля 2020

Я пытаюсь понять, как Rust работает с памятью, и у меня есть небольшая программа, которая печатает некоторые адреса памяти:

fn main() {
    let a = &&&5;
    let x = 1;
    println!(" {:p}", &x);
    println!(" {:p} \n {:p} \n {:p} \n {:p}", &&&a, &&a, &a, a);
}

Это печатает следующее (различается для разных прогонов):

0x235d0ff61c
0x235d0ff710 
0x235d0ff728 
0x235d0ff610 
0x7ff793f4c310

На самом деле это сочетание 40-битных и 48-битных адресов. Почему эта смесь? Кроме того, может кто-нибудь сказать мне, почему адреса (2, 3, 4) не попадают в места, разделенные 8 байтами (так как std::mem::size_of_val(&a) дает 8)? Я использую Windows 10 на процессоре AMD x-64 (Phenom || X4) с 24 ГБ ОЗУ.

Ответы [ 2 ]

3 голосов
/ 07 апреля 2020

На самом деле это сочетание 40-битных и 48-битных адресов. Почему этот микс?

Это не совсем микс, Rust просто не отображает начальные нули. На самом деле все зависит от того, где ОС отображает различные компоненты программы (data, bss, heap и stack) в адресном пространстве.

Также, может кто-нибудь подскажет, почему адреса (2, 3 , 4) не попадают в места, разделенные 8-байтами (так как std :: mem :: size_of_val (& a) дает 8)?

Поскольку println! - это макрос, который расширяется в пучок вещей в стеке, поэтому ваши значения не определены рядом друг с другом в конечном коде фрейма (https://play.rust-lang.org/?version=stable&mode=debug&edition=2018&gist=5b812bf11e51461285f51f95dd79236b). Хотя даже если бы они были, не было бы никакой гарантии, что компилятор, например, не будет повторно использовать уже мертвую память, чтобы сэкономить на размере кадра.

3 голосов
/ 07 апреля 2020

Все адреса имеют одинаковый размер, Rust просто не печатает последние 0 цифр.

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

См. Результат компиляции на https://godbolt.org/z/kzSrDr:

.L__unnamed_4 содержит значение 5; .L__unnamed_5, .L__unnamed_6 и .L__unnamed_1 являются &5 &&5 и &&&5.

Итак, .L__unnamed_1 - это то, что в вашей системе находится на 0x7ff793f4c310. Пока 0x235d0ff??? находится в вашем стеке и рассчитывается в красной и синей областях кода.

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