|
|
  |
IAR: Warning[Pa082]:, переменные volatile |
|
|
|
Feb 26 2006, 19:29
|

Гуру
     
Группа: Свой
Сообщений: 2 720
Регистрация: 24-03-05
Пользователь №: 3 659

|
Доброго времени суток! Столкнулся с таким сообщением IAR Atmel AVR C/C++ Compiler V4.10B/W32, Evaluation Version Имеется код: Код char volatile Line_Lenght1, Line_Lenght2; char volatile Area_Height, Area_Width;
...
где-то в коде:
void Fun(void){
...
Area_Width = Line_Lenght1 + Line_Lenght2;
...
} Для строчки "Area_Width = Line_Lenght1 + Line_Lenght2;" выводится предупреждение типа: Warning[Pa082]: undefined behavior: the order of volatile accesses is undefined in this statement
И так почти во всех местах, где производятся операции с несколькими "volatile". Проект отлично работает, но данные предупреждения немного раздражают. Привык, что проект компилируется "чисто", без Warning-ов. Может кто знает, как победить их?
--------------------
|
|
|
|
|
Feb 26 2006, 19:41
|
Знающий
   
Группа: Свой
Сообщений: 550
Регистрация: 16-06-04
Из: Казань
Пользователь №: 32

|
Вот так: Код Area_Width = Line_Lenght1; Area_Width += Line_Lenght2; и т. п. PS: а так ли нужно объявлять volatile-ами с виду самые обычные переменные?
--------------------
Главная линия этого опуса ясна мне насквозь!
|
|
|
|
|
Feb 26 2006, 19:53
|

Гуру
     
Группа: Свой
Сообщений: 2 720
Регистрация: 24-03-05
Пользователь №: 3 659

|
Цитата(vet @ Feb 27 2006, 02:41)  Вот так: Код Area_Width = Line_Lenght1; Area_Width += Line_Lenght2; и т. п. PS: а так ли нужно объявлять volatile-ами с виду самые обычные переменные? Это глобальные переменные, и при максимальной оптимизации, нектороые "оптимизируются", выкидываются вместе скодом, проще говоря :-) Строка Код Area_Width += Line_Lenght2; имеет то же самое предупреждение. А как быть с кодом Код if(Line_Lenght1==Line_Lenght2){
} с точно таким же предупреждением?
--------------------
|
|
|
|
|
Feb 26 2006, 20:11
|

Гуру
     
Группа: Свой
Сообщений: 2 720
Регистрация: 24-03-05
Пользователь №: 3 659

|
Цитата(vet @ Feb 27 2006, 02:57)  Они так и будут появляться, всё ж заvolatilено Компилятор выкидывает при оптимизации то, что не влияет на результат вычислений, глобальность тут ни при чём. volatile имеет смысл применять в особых ситуациях - сделать задержку, вывести данные в порт и т. п. Здесь же компилятор справедливо указывает, что одно из нескольких volatile будет прочитано/записано раньше. Можно отменить это предупреждение совсем. Но лучше убрать volatile-ы и дать компилятору развернуться с оптимизацией  Угу...сделал в точности так, код работает максимум на медиум, но ни как ни на максимальной (по размеру кода) оптимизации, и, естественно, раздулся...
--------------------
|
|
|
|
|
Feb 26 2006, 20:34
|

кекс
     
Группа: Свой
Сообщений: 3 825
Регистрация: 17-12-05
Из: Киев
Пользователь №: 12 326

|
Цитата(prottoss @ Feb 26 2006, 21:29)  Компилятор хочет атомарности операций.. обеспечте ему их.. char temp; temp = Line_Lenght2; Area_Width = Line_Lenght1; Area_Width += temp; а какой смысл делать все переменные volatile? Делайте volatile только те, которые изменяются в разных трэдах. Цитата Угу...сделал в точности так, код работает максимум на медиум, но ни как ни на максимальной (по размеру кода) оптимизации, и, естественно, раздулся... Вам памяти в чипе не хватает? Ну раздулся код и Бог с ним, зато возможно работать будет быстрее.
|
|
|
|
|
Feb 26 2006, 21:56
|

Гуру
     
Группа: Свой
Сообщений: 2 720
Регистрация: 24-03-05
Пользователь №: 3 659

|
Решил проблему... В модуле 12 глобальных переменных и порядка 20-и функций обращающихся произволно к нескольким переменным. Если не ставил к типу переменной volatile, некторые переменные "оптимизировались". Объединил все переменные в одну структуру. Все всало на свои места. Компилятор перестал предупреждать, да и код стал поменьше немножко, что льстит моему эго :-). Просмотрел листинг - компилер, вместо загрузки в указатель адреса переменной стал в начале функции формировать указатель на структуру, а к элементам обращается по индексу. Красиво, блин. Всем спасибо за советы. Цитата(defunct @ Feb 27 2006, 03:34)  Цитата(prottoss @ Feb 26 2006, 21:29)  Компилятор хочет атомарности операций.. обеспечте ему их.. char temp; temp = Line_Lenght2; Area_Width = Line_Lenght1; Area_Width += temp; Это не помогает Цитата(defunct @ Feb 27 2006, 03:34)  а какой смысл делать все переменные volatile? Делайте volatile только те, которые изменяются в разных трэдах. Согласен, смысла нет. Но на момент отладки так надежнее, я считаю. Цитата(defunct @ Feb 27 2006, 03:34)  Цитата Угу...сделал в точности так, код работает максимум на медиум, но ни как ни на максимальной (по размеру кода) оптимизации, и, естественно, раздулся... Вам памяти в чипе не хватает? Ну раздулся код и Бог с ним, зато возможно работать будет быстрее. Я не люблю "возможно". Я пытаюсь всегда знать, что и как делает компилятор. Возможно ( :-) ), по этому в моем коде редкИ глюки :-)
--------------------
|
|
|
|
|
Feb 26 2006, 23:26
|
Группа: Новичок
Сообщений: 8
Регистрация: 16-02-06
Пользователь №: 14 395

|
Эх, когда же начнут читать документацию? Volatile означает, что компилятору и оптимизатору запрещается делать какие-либо предположения относительно значения данной переменной, и обязательно необходимо читать эту переменную перед тем, как делать с ней что-либо (конечно, если эта переменная находится не в регистре, а в памяти). Больше ничего volatile не означает. Откуда берется предупреждение: в вашем коде присутствует конструкция Area_Width = Line_Lenght1 + Line_Lenght2; в которой все переменные - volatile. Если с присваиванием никаких вопросов у компилятора не возникает, то относительно конструкции Line_Length1 + Line_Length2 компилятор не знает, в каком порядке нужно прочитать значения переменных перед выполнением сложения - сначла первую, потом вторую, или наоборот. Очевидно, что результат может зависить от порядка, если значения переменных меняются, например, в ISR. И именно об этом компилятор вам и выводит предупреждение: он не может дать гарантии, в каком порядке произойдет чтение этих переменных перед сложением. А теперь внимание, советы, которые здесь давали. Ни в коем случае не стоит делать такой код! Цитата Area_Width = Line_Length1; Area_Width += Line_Length2; Он скомпилируется примерно в такое: Загрузить Line_Length1 в регистр Загрузить регистр в Area_Width Загрузить Area_Width в регистр (это компилятор делает, так как Area_Width - тоже volatile и он мог измениться между этими двумя инструкциями) Загрузить Line_Length2 в регистр Сложить Загрузить регистр в Area_Width Как сделать правильно: Цитата register char tmp tmp = Line_Length1; Area_Width = tmp + Line_Length2; Это скомпилируется в: загрузить Line_Length1 в регистр загрузить Line_Length2 в регистр Сложить Загрузить регистр в Area_Width А вообще, почитайте документацию от IAR'а, которая идет в PDF'ах. Там много интересного пишут.
|
|
|
|
|
Feb 27 2006, 14:30
|

Adept
     
Группа: Свой
Сообщений: 3 469
Регистрация: 6-12-04
Из: Novosibirsk
Пользователь №: 1 343

|
Цитата(Alechin @ Feb 27 2006, 19:34)  Насчет выкидывания volatile: при этом действительно можно получить неработоспособный код - IAR "слишком умный" - если в какой-либо процедуре идет чтение глобальной переменной, и перед этим в процедуре нет записи в нее - компилятор использование этой переменной молча (заметьтьте - молча) выбрасывает из кода. Я для MSP430 очень долго не мог понять - почему основной цикл программы с условием завершения по такой, не описанной как volatile, переменной полностью был исключен из кода! Компилятор посчитал, что раз переменная в цикле нигде не модифицируется, то цикл никогда не будет выполнен. И совершенно правильно он делает. И то, что докапывается до этого - честь ему и хвала, потому как действительно дотошный и придирчивый компилятор, генерирующий хороший код, глядя на который, писать что-то на асме пропадает в подавляющем большинстве случаев само собой. Что касается volatile. Volatile, как сказали, указание компилятору не оптимизировать объект. На самом деле это не совсем правильно, не совсем точно. Volatile - более близкий по смыслу перевод, - означает, что объект "подвижный", асинхронно изменяемый, т.е. объект может быть срытно изменен вне данного потока управления программы. И, следовательно, запрещает не все оптимизации, а только те, которые могут нарушить правильность работы по причине асинхронной изменяемости. Другие оптимизации вполне имеют право быть. Например, есть в EWAVR оптимизация clustering variables. Она сводится к тому, что компилятор логически объединяет рядом объявленные глобальные/статические объекты в "вируальную структуру" и обращается к этим объектам, не загружая каждый раз полный адрес для каждого объекта, а загрузив одни раз базовый адрес этой "виртуальной структуры", обращается к объектам со смещением, что есть наиболее эффективный способ адресации в AVR. И если пропускать обращение к объекту, объявленному как volatile, компилятор не имеет права, то делать кластеризацию с этим объектом - пожалуйста. Т.ч. тут все не в компилятор упирается, а в программиста. Ошибка эта очень распространенная, все на эти грабли наступают и не один раз. И даже опытные товарищи забывают (вернее, упускают из виду) и тоже мимо граблей не проходят. Но откаываться от хорошей оптимизации, имхо, все-таки неправильно.
--------------------
«Отыщи всему начало, и ты многое поймёшь» К. Прутков
|
|
|
|
|
Feb 28 2006, 11:32
|
Частый гость
 
Группа: Свой
Сообщений: 158
Регистрация: 27-06-05
Из: Химки, Моск.обл.
Пользователь №: 6 334

|
Цитата(vet @ Feb 27 2006, 17:33)  Alechin Можно глянуть на пример? для общего развития, чтоб лишний раз на грабли не наступать. К сожалению давно это было - сейчас ничего не осталось. В приниципе можно написать самому тестовый пример (будет хорошей практикой). Главное сделать 2 модуля (файла). Обращаться из одного файла к переменной в другом файле (сделав ее "видимой"). Вернее даже не обращаться, а сделать по ней цикл, или ветвление, и посмотрить сгенерированный листинг. А насчет ИАРа - все-таки варнинг надо было сделать на "с оптимизированный" код. Что бы не пришлось голову ломать. Ведь если бы я тогда не посмотрел исходник - никогда бы не понял, что произошло.
|
|
|
|
|
  |
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|