2014 dxdy logo

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

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




Начать новую тему Ответить на тему На страницу Пред.  1, 2, 3, 4, 5  След.
 
 Re: Вопрос по работе компилятора C++
Сообщение01.03.2017, 14:37 
Заслуженный участник
Аватара пользователя


16/07/14
8336
Цюрих
Pavia в сообщении #1196222 писал(а):
Если не доступно, то никак будет ошибка.
Неправда. Можно вызывать функцию, для которой доступно только declaration, но не definition.
Pavia в сообщении #1196222 писал(а):
Почему не может? Может.
Потому что как он должен угадать, где лежит определение? С учетом того, что в момент компиляции его может вообще не существовать.

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

 Профиль  
                  
 
 Re: Вопрос по работе компилятора C++
Сообщение01.03.2017, 14:53 
Аватара пользователя


31/10/08
1244
mihaild
Да. Согласен. Видимо термины по путал.

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

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

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


10/04/12
704
mihaild в сообщении #1196229 писал(а):
Все определения целиком доступны только линковщику, но не компилятору.


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

 Профиль  
                  
 
 Re: Вопрос по работе компилятора C++
Сообщение01.03.2017, 15:38 
Заслуженный участник


20/08/14
11058
Россия, Москва

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

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

 Профиль  
                  
 
 Re: Вопрос по работе компилятора C++
Сообщение01.03.2017, 16:09 
Заслуженный участник
Аватара пользователя


30/01/06
72407
Dmitriy40
Возможно, проверки были в более ранних процессорах, типа 386, а сейчас убраны? А документ описывает современную архитектуру.

 Профиль  
                  
 
 Re: Вопрос по работе компилятора C++
Сообщение01.03.2017, 16:52 
Заслуженный участник


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

 Профиль  
                  
 
 Re: Вопрос по работе компилятора C++
Сообщение01.03.2017, 17:02 
Аватара пользователя


31/10/08
1244
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 
Заслуженный участник


04/05/09
4582
Вообще-то при возврате из прерывания RSP восстанавливается из фрейма прерывания.
Т.е. процедура прерывания вызывается со стеком выровненным на 16 байт, но ничто не мешает тут-же в процедуре нарушить выравнивание опять, восстановить перед возвратом из прерывания, и IRET восстановит исходный не выровненный RSP прерванного кода.

 Профиль  
                  
 
 Re: Вопрос по работе компилятора C++
Сообщение01.03.2017, 17:43 
Заслуженный участник


20/08/14
11058
Россия, Москва
Pavia
Хм, наверное я что-то непонимаю. Тут ведь сказано что выровнен будет новый кадр стека, в самом прерывании, но не старый RSP, который восстановится до байта при возврате. Т.е. с невыровненным стеком будет прерывание, RSP выровняется на 16 байт, потом в стек засунется и адрес возврата и исходный RSP и прочее. Т.е. при возврате искажения RSP не произойдёт, это лишь в самом прерывании стек будет выровнен всегда на 16 байтов.
Проверка алгоритма команды INT тоже указывает на push в стек правильного старого указателя стека, вовсе не нового выровненного.
И всё это только для x64 режима.

 Профиль  
                  
 
 Re: Вопрос по работе компилятора C++
Сообщение01.03.2017, 18:02 
Аватара пользователя


31/10/08
1244
Был у меня код с невыровненном стеком(своя ОС, ошибка была на Ring0), но там было ещё несколько условий. Которые недовали восстановить стек. И вот их то я как раз и непомню. По отдельности все условия безобидны и схема с восстановлением должна была работать, но на практике все вместе давали эффект аппаратной ошибки. А устранить можно было только выравниванием стека. Другие способы приводили к другим ошибкам.

 Профиль  
                  
 
 Re: Вопрос по работе компилятора C++
Сообщение01.03.2017, 19:06 
Заслуженный участник


20/08/14
11058
Россия, Москва
Да, какая-то проблема есть с выравниванием стека, но только в 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 
Заслуженный участник
Аватара пользователя


30/01/06
72407
Dmitriy40 в сообщении #1196271 писал(а):
Книга: В.Л.Григорьев, Микропроцессор i486: Архитектура и программирование. ISBN 5-900676-01-3. Противоречий с документацией Intel не замечено.

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

 Профиль  
                  
 
 Re: Вопрос по работе компилятора C++
Сообщение01.03.2017, 20:33 


11/12/14
893
Dmitriy40 в сообщении #1196304 писал(а):
(не разбирался зачем такая)


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

 Профиль  
                  
 
 Re: Вопрос по работе компилятора C++
Сообщение01.03.2017, 22:26 


09/05/10
122
Ростов-на-Дону
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 
Заслуженный участник


20/08/14
11058
Россия, Москва
Tod Leben
Первая Ваша цитата к выравниванию стека никакого отношения не имеет.
Вторая цитата - тоже в общем-то, там речь про выравнивание всех обращений к памяти, а не только к стеку. И как я уже сказал выше, это включается лишь для отладки программ и думаю давно никем не используется.

 Профиль  
                  
Показать сообщения за:  Поле сортировки  
Начать новую тему Ответить на тему  [ Сообщений: 61 ]  На страницу Пред.  1, 2, 3, 4, 5  След.

Модераторы: Karan, Toucan, PAV, maxal, Супермодераторы



Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей


Вы не можете начинать темы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете добавлять вложения

Найти:
Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group