Требуется ли для _printf предустановленное пространство в стеке? [Дубликат]

Я искал решение, позволяющее работать $.bind и $.unbind без проблем в динамически добавленных элементах.

Поскольку on () делает трюк для присоединения событий, чтобы создать фальшивую отвязку на тех, к которым я пришел:

const sendAction = function(e){ ... }
// bind the click
$('body').on('click', 'button.send', sendAction );

// unbind the click
$('body').on('click', 'button.send', function(){} );

3
задан 齐天大圣 11 April 2017 в 19:29
поделиться

1 ответ

Как вы сказали, MacOS X имеет выравнивание по 16 байт, что означает, что машина ожидает, что каждая переменная в стеке начнется с байта, который кратен 16 из текущего указателя стека.

Когда стопка смещена, это означает, что мы начинаем пытаться читать переменные из середины этого 16-байтового окна и обычно заканчиваем с ошибкой сегментации.

Прежде чем вы вызовите рутину в своем коде, вам нужно чтобы убедиться, что ваш стек правильно выровнен; в этом случае, что означает, что регистр базового указателя делится на 16.

subq $8, %rsp               # stack is misaligned by 8 bytes
movq %rdi, 8(%rsp)          #
movq obj_size(%rdi), %rax   #
imul $8, %rax               #
movq %rax, %rdi             #
callq _malloc               # stack is still misaligned when this is called

Чтобы исправить это, вы можете subq %rsp получить что-то вроде 16 вместо 8.

subq $16, %rsp               # stack is still aligned
movq %rdi, 16(%rsp)          #
...                          #
callq _malloc                # stack is still aligned when this is called, good
3
ответ дан Nick Zuber 18 August 2018 в 04:23
поделиться
  • 1
    , что означает, что компилятор ожидает, что каждая переменная будет определена в 16-байтовом слоте памяти . Нет, это не то, что это значит. Ширина слотов arg в стеке равна 8, но первая первая находится по адресу с 16-байтовым выравниванием. Но да, push %rbp в функции пролог выровнял стек на 16, поэтому необходимо вычесть кратное 16 при резервировании пространства стека. – Peter Cordes 14 February 2018 в 03:35
  • 2
    @PeterCordes А я вижу, спасибо за исправление! Есть ли что-то еще неправильное или что я должен добавить здесь? – Nick Zuber 14 February 2018 в 03:42
  • 3
    означает, что регистр базового указателя делится на 16. Выравнивание rbp не имеет ничего общего с чем-либо; ABI не указывает ничего о том, как используется RBP. RBP равен 16 байт, выровненному в сломанном коде OP, потому что он всегда установлен на rsp_on_entry-8, когда вы создаете традиционный фрейм стека, так что это явно не является достаточным условием. Кроме того, ваш первый абзац все еще не прав. Первый arg начинается с 16-байтового выровненного адреса, но позже args (если есть) выравниваются только по 8 байт, если только этот конкретный arg не имеет более высокого требования к выравниванию (например, long double или __m128). – Peter Cordes 14 February 2018 в 04:12
Другие вопросы по тегам:

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