2014 dxdy logo

Научный форум dxdy

Математика, Физика, Computer Science, Machine Learning, LaTeX, Механика и Техника, Химия,
Биология и Медицина, Экономика и Финансовая Математика, Гуманитарные науки




На страницу Пред.  1, 2, 3, 4, 5  След.
 
 Re: Вопрос по работе компилятора C++
Сообщение01.03.2017, 14:37 
Аватара пользователя
Pavia в сообщении #1196222 писал(а):
Если не доступно, то никак будет ошибка.
Неправда. Можно вызывать функцию, для которой доступно только declaration, но не definition.
Pavia в сообщении #1196222 писал(а):
Почему не может? Может.
Потому что как он должен угадать, где лежит определение? С учетом того, что в момент компиляции его может вообще не существовать.

Все определения целиком доступны только линковщику, но не компилятору.

 
 
 
 Re: Вопрос по работе компилятора C++
Сообщение01.03.2017, 14:53 
Аватара пользователя
mihaild
Да. Согласен. Видимо термины по путал.

-- Ср мар 01, 2017 16:01:27 --

Tod Leben
Dmitriy40
Не ссорьтесь Стек и правда должен быть выровнен. Другое дело что проверки процессор делает крайне редко. Насколько помню проблемы возникают при возврате из прерывания.

 
 
 
 Re: Вопрос по работе компилятора C++
Сообщение01.03.2017, 15:18 
mihaild в сообщении #1196229 писал(а):
Все определения целиком доступны только линковщику, но не компилятору.


Недоступны полностью и линковщику, вполне можно вызвать функцию из so-файла таргета, который может отсутствовать и/или различаться для данного хоста.

 
 
 
 Re: Вопрос по работе компилятора C++
Сообщение01.03.2017, 15:38 

(Выравнивание стека)

Да мне реально интересны две вещи: в какой момент можно получить неожиданный крэш из-за невыравненного стека; и почему об этом не написано в доке интела. Я конечно всю её не изучал - 3460 страниц это убиться можно - но ни для одной команды не встречал описания исключения из-за выравнивания стека.
Pavia в сообщении #1196235 писал(а):
Насколько помню проблемы возникают при возврате из прерывания.
Неа, ни для CALL, ни для RET, ни для IRET команд не указаны исключения из-за невыравненного стека, только non-canonical form и только для x64 режима, а это совсем другое. Ну ткните уже носом в доку где выравнивание требуется? Может у меня из-за этого некоторые программы изредка вылетают ... :-(

 
 
 
 Re: Вопрос по работе компилятора C++
Сообщение01.03.2017, 16:09 
Аватара пользователя
Dmitriy40
Возможно, проверки были в более ранних процессорах, типа 386, а сейчас убраны? А документ описывает современную архитектуру.

 
 
 
 Re: Вопрос по работе компилятора C++
Сообщение01.03.2017, 16:52 
Вряд ли. Полного подробного описания 8086 у меня под рукой нет, открыл первую попавшуюся книгу, в нём вообще нет исключений выравнивания данных. Никаких.
Про i486 я уже говорил, там исключение выравнивания есть, для любых данных в памяти, но включается лишь для отладки программ и думаю уже давно никем не используется (слишком много проблем с кривыми указателями). Про выравнивание именно стека нигде ничего не сказано. Книга: В.Л.Григорьев, Микропроцессор i486: Архитектура и программирование. ISBN 5-900676-01-3. Противоречий с документацией Intel не замечено.
Ослабления требований выравнивания были (и надеюсь продолжатся) лишь в части MMX/SSE/AVX команд, стек здесь нипричём.
К тому же товарищ говорил вообще про реальный режим ...

 
 
 
 Re: Вопрос по работе компилятора C++
Сообщение01.03.2017, 17:02 
Аватара пользователя
Munin
Да современную. И проверки остались. Просто там в одном месте описаны, что они есть, а вот где они происходят описано в другом. Возможно даже в другом томе. Если интересно могу вечером привести цитату если найду.

Dmitriy40
6.14.2 64-Bit Mode Stack Frame
...
In legacy mode, the stack pointer may be at any alignment when an interrupt or exception causes a stack frame to
be pushed. This causes the stack frame and succeeding pushes done by an interrupt handler to be at arbitrary
alignments. In IA-32e mode, the RSP is aligned to a 16-byte boundary before pushing the stack frame. The stack
frame itself is aligned on a 16-byte boundary when the interrupt handler is called. The processor can arbitrarily
realign the new RSP on interrupts because the previous (possibly unaligned) RSP is unconditionally saved on the
newly aligned stack. The previous RSP will be automatically restored by a subsequent IRET.
* - тут у интел несовсем верно пишет. IA-32 тоже подвержен ошибкам. Только ему нужно выравнивание до 2 байт.

При заходе в прерывание процессор тупо обнуляет младшие биты ESP/RSP и потом закидывает этот адрес в стековый фрейм для возврата из прерывания. Так как он сохраняет выровненный адрес, то возврат идёт тоже по выровненному. А ваша программа ожидает что стек останется произвольным.
Допустим случилось прерывание от таймера.
До прерывания ESP был 1027 после возврата он стал 1024. Ваша программа начинает писать по адресу ESP и попадает вместо 1027 в 1024 и портим стек.



Цитата:
IF (IA32_EFER.LMA = 0) (* Not IA-32e mode *)
THEN
IF instruction pointer from IDT gate is not within new code-segment limit
THEN #GP(EXT); FI; (* Error code contains NULL selector *)
ELSE
IF instruction pointer from IDT gate contains a non-canonical address
THEN #GP(EXT); FI; (* Error code contains NULL selector *)
RSP ← NewRSP & FFFFFFFFFFFFFFF0H;


А проверку на non-canonical - можно отключить если правильно понимаю.

 
 
 
 Re: Вопрос по работе компилятора C++
Сообщение01.03.2017, 17:18 
Вообще-то при возврате из прерывания RSP восстанавливается из фрейма прерывания.
Т.е. процедура прерывания вызывается со стеком выровненным на 16 байт, но ничто не мешает тут-же в процедуре нарушить выравнивание опять, восстановить перед возвратом из прерывания, и IRET восстановит исходный не выровненный RSP прерванного кода.

 
 
 
 Re: Вопрос по работе компилятора C++
Сообщение01.03.2017, 17:43 
Pavia
Хм, наверное я что-то непонимаю. Тут ведь сказано что выровнен будет новый кадр стека, в самом прерывании, но не старый RSP, который восстановится до байта при возврате. Т.е. с невыровненным стеком будет прерывание, RSP выровняется на 16 байт, потом в стек засунется и адрес возврата и исходный RSP и прочее. Т.е. при возврате искажения RSP не произойдёт, это лишь в самом прерывании стек будет выровнен всегда на 16 байтов.
Проверка алгоритма команды INT тоже указывает на push в стек правильного старого указателя стека, вовсе не нового выровненного.
И всё это только для x64 режима.

 
 
 
 Re: Вопрос по работе компилятора C++
Сообщение01.03.2017, 18:02 
Аватара пользователя
Был у меня код с невыровненном стеком(своя ОС, ошибка была на Ring0), но там было ещё несколько условий. Которые недовали восстановить стек. И вот их то я как раз и непомню. По отдельности все условия безобидны и схема с восстановлением должна была работать, но на практике все вместе давали эффект аппаратной ошибки. А устранить можно было только выравниванием стека. Другие способы приводили к другим ошибкам.

 
 
 
 Re: Вопрос по работе компилятора C++
Сообщение01.03.2017, 19:06 
Да, какая-то проблема есть с выравниванием стека, но только в x64 режиме и похоже не в прерываниях, а лишь внутри WinAPI. Написал проверочный код на чистом асме:
Используется синтаксис ASM
        sub     RSP,8*5
        mov     R9,RSP
        or      RSP,9
        mov     R8,RSP
        mov     RCX,10000000000
@l:     push    R11
        pop     R11
        cmp     R8,RSP
        jne     @fail
        dec     RCX
        jnz     @l
@fail:  mov     RSP,R9
После него вызываются две функции WinAPI (вывод сообщения и ExitProcess). И вот если в конце RSP не восстановить - в момент вызова функций WinAPI программа вылетает. Но за десятки секунд прерываний было явно море и ни одно из них не приводит к проблемам внутри цикла.

-- 01.03.2017, 19:36 --

Протрассировал функцию MessageBoxA до ошибки, там (в lpk.dll) вcтретилась команда
Используется синтаксис ASM
movaps [RSP+150h],xmm8
(не разбирался зачем такая), ну и разумеется при невыровненном на 16 байт стеке она вылетает. Так что не в процессоре дело, в программах. :facepalm:

 
 
 
 Re: Вопрос по работе компилятора C++
Сообщение01.03.2017, 19:41 
Аватара пользователя
Dmitriy40 в сообщении #1196271 писал(а):
Книга: В.Л.Григорьев, Микропроцессор i486: Архитектура и программирование. ISBN 5-900676-01-3. Противоречий с документацией Intel не замечено.

Ну вы же понимаете, что эти книги при всём желании не могут полно излагать многотомные Intel-овские мануалы... Впрочем, насчёт отладочного режима - похоже на правду.

 
 
 
 Re: Вопрос по работе компилятора C++
Сообщение01.03.2017, 20:33 
Dmitriy40 в сообщении #1196304 писал(а):
(не разбирался зачем такая)


Подозреваю, что для True Type Fonts нужна и субпиксельная и, соответственно, вещественная точность.

 
 
 
 Re: Вопрос по работе компилятора C++
Сообщение01.03.2017, 22:26 
Dmitriy40
Цитата:
Страничный сбой при противоречивом значении указателя стека

Следует обращать особое внимание на то, чтобы страничный сбой не приводил к использованию процессором неверного указателя стека (SS:ESP). Программное обеспечение, написанное для 16-битовых процессоров Intel, часто использует для переключения на новый стек пару команд, например,

MOV SS, AX
MOV SP, StackTop

В случае процессора i486+, поскольку вторая команда обращается к памяти, можно получить в данном случае страничный сбой после того, как был изменен селектор сегментного регистра SS, но перед тем, как соответственно было изменено содержимое регистра SP. В этой точке две части указателя стека SS:SP (разумеется, для 32-разрядных программ это SS:ESP) противоречивы друг с другом. Новый стековый сегмент используется со старым указателем стека.
Процессор не использует противоречащий указатель стека, если обработка страничного сбоя вызывает переключение стека на хорошо определенный стек (т.е. обработчик это задача или более привилегированная процедура). Однако, если страничный сбой происходит на том же уровне привилегированности и в той же задаче, что и для обработчика страничного сбоя, то процессор попытается использовать стек, на который указывает противоречивый указатель стека.
В системах, использующих подкачку страниц и обрабатывающих страничные сбои в пределах задач, содержащих сбой (посредством шлюзов ловушки или прерывания), программное обеспечение, выполняемое на том же уровне привилегированности, что и обработчик страничного сбоя, должно инициализировать новый стек командой LSS, а не парой команд, показанной выше. Если обработчик страничного сбоя работает на уровне привилегированности 0 (нормальный случай), проблема ограничивается программами, работающими на уровне привилегированности 0, т.е. обычно ядром операционной системы.


Цитата:
Сбой проверки выравнивания может генерироваться при доступе к невыравненным операндам. Например, слово, записанное по нечетному адресу памяти, или двойное слово, записанное по адресу, не кратному четырем. В таблице ниже приводятся требования к выравниванию по типам данных. Для разрешения контроля выравнивания должны выполняться следующие условия:

· Бит AM регистра CR0 должен быть установлен;
· Флаг AC должен быть установлен;
· CPL должен быть равен 3 (уровень пользователя).

-----------------------------------------------------------------
Тип данных Адрес должен нацело делиться на
-----------------------------------------------------------------
Слово 2
Двойное слово 4
Короткое вещественное 4
Длинное вещественное 8
Временное вещественное 8
Селектор 2
48-разрядный сегментированный указатель 4
32-разрядный плоский указатель 4
32-разрядный сегментированный указатель 2
48-разрядный "Псевдо-дескриптор" 4
Область хранения FSTENV/FLDENV 4 или 2, в зависимости от размера операнда
Область хранения FSAVE/FRSTOR 4 или 2, в зависимости от размера операнда
Битовая строка 4
-----------------------------------------------------------------

Проверку выравнивания полезно использовать в программах, в которых два младших бита указателей служат для идентификации адресуемой ими структуры данных. Например, подпрограмма в библиотеке математических функций может принимать указатели на числовые структуры данных. Если типу этой структуры в двух младших битах указателей на этот тип назначен код 10 (двоичный), математические подпрограммы могут выполнить для этого кода типа коррекцию, добавляя смещение -10 (двоичное). Если подпрограмма получит неверный тип указателя, то произойдет невыравненная ссылка, что приведет к генерации исключения.
Сбои проверки выравнивания генерируются только в режиме пользователя (уровень привилегированности 3). Ссылки к памяти с уровнем привилегированности по умолчанию 0, такие как загрузка дескриптора сегмента, не генерируют сбоев проверки выравнивания, даже если они вызваны ссылками к памяти, выполненными в пользовательском режиме.
Запись 48-разрядного псевдо-дескриптора (образа памяти для содержимого базового регистра таблицы дескрипторов) в режиме пользователя может генерировать сбой проверки выравнивания. Хотя программы режима пользователя обычно не сохраняют псевдодескрипторов, такого сбоя можно избежать, выравнивая псевдодескриптор по адресу нечетного слова (т.е. адресу, являющемуся 2 MOD 4).
Команды FSAVE и FRSTOR генерируют невыравненные ссылки, которые могут вызвать сбой проверки выравнивания. Прикладным программам эти команды нужны редко.

 
 
 
 Re: Вопрос по работе компилятора C++
Сообщение01.03.2017, 22:52 
Tod Leben
Первая Ваша цитата к выравниванию стека никакого отношения не имеет.
Вторая цитата - тоже в общем-то, там речь про выравнивание всех обращений к памяти, а не только к стеку. И как я уже сказал выше, это включается лишь для отладки программ и думаю давно никем не используется.

 
 
 [ Сообщений: 61 ]  На страницу Пред.  1, 2, 3, 4, 5  След.


Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group