реклама на сайте
подробности

 
 
5 страниц V  < 1 2 3 4 > »   
Reply to this topicStart new topic
> Ошибка IAR или чтото еще?
singlskv
сообщение Dec 18 2006, 19:31
Сообщение #16


дятел
*****

Группа: Свой
Сообщений: 1 681
Регистрация: 13-05-06
Из: Питер
Пользователь №: 17 065



Цитата(Oldring @ Dec 18 2006, 19:08) *
Дело в том, что Билл написал просто чепуху про "естественную" свертку целочисленных констант перед вычислением выражения, а Вашего предложения я вообще почему-то не вижу в истории переписки. Так как так и не была озвучена информация про диапазоны операндов, хотелось бы все-таки увидеть, что именно Вы считаете "правильной" записью данного выражения, если это понятие "правильности" отличется от формальной правильности. Хотелось бы также узнать Ваше мнение по следующему вопросу: существует ли с точки зрения стандарта языка программирования С какая-либо разница между выражениями

Код
a * b * c / d


и

Код
((a * b) * c)  / d


?

Попробую с Вами не согласиться.
Предположим у нас есть такой код
Код
  tmp=a+153+b-35

позволим компилятору преобразовать это в
Код

tmp=a+118+b

?
или нет ?

Замечу что + и - имеет один уровень приоритета

* и / тоже один уровень
Go to the top of the page
 
+Quote Post
Oldring
сообщение Dec 18 2006, 19:38
Сообщение #17


Гуру
******

Группа: Свой
Сообщений: 3 041
Регистрация: 10-01-05
Из: Москва
Пользователь №: 1 874



Ответ прост. До тех пор, пока результат вычисления всего целочисленного выражения не отличается от стандартного способа вычисления с учетом того, что при переполнении промежуточных результатов возможно undefined поведение, компилятор может делать все, что угодно. Но только пока не отличается. Более того, важен даже не результат вычисления одного выражения, а последовательность записи значений в volatile переменные и вызовов системных функций. Все оптимизации программы, которые сохраняют запись в volatile переменные и ызовы системных функций - законные, все, которые приводят к изменению внешнего поведения программы - незаконны.


--------------------
Пишите в личку.
Go to the top of the page
 
+Quote Post
singlskv
сообщение Dec 18 2006, 19:53
Сообщение #18


дятел
*****

Группа: Свой
Сообщений: 1 681
Регистрация: 13-05-06
Из: Питер
Пользователь №: 17 065



Цитата(Oldring @ Dec 18 2006, 19:38) *
Ответ прост. До тех пор, пока результат вычисления всего целочисленного выражения не отличается от стандартного способа вычисления с учетом того, что при переполнении промежуточных результатов возможно undefined поведение, компилятор может делать все, что угодно. Но только пока не отличается. Более того, важен даже не результат вычисления одного выражения, а последовательность записи значений в volatile переменные и вызовов системных функций. Все оптимизации программы, которые сохраняют запись в volatile переменные и ызовы системных функций - законные, все, которые приводят к изменению внешнего поведения программы - незаконны.

Наверное все-таки так:
- если мы отключаем оптимизацию полностью
- если мы отключаем все расширения компилятора отличные от стандарта
- если мы все переменные объявляем как volatile
то тогда да, компилятор обязан сделать все как ему написали.

А вот если мы все выше перечисленное включили, то
Добро пожаловать в Manual для выяснения всех подробностей как и что
себе думает компилятор при оптимизации (если конечно авторы не забыли это указать smile.gif )
Go to the top of the page
 
+Quote Post
Oldring
сообщение Dec 18 2006, 20:08
Сообщение #19


Гуру
******

Группа: Свой
Сообщений: 3 041
Регистрация: 10-01-05
Из: Москва
Пользователь №: 1 874



Не совсем.

1. Включение оптимизации самой по себе не отменяет требования соблюдения компилятором стандарта языка.
2. Расширения компилятора учитывать стоит - но их обычно немного и они описаны в описании компилятора. Расширения для 8-битников могут затрагивать аривметику с 8-битными числами - не расширять до int например - но я в первый раз слышу чтобы расширения затрагивали вычисления unsigned long.
3. Нет. Компилятор обязан сделать чтобы снаружи выглядело как ему написали в любом случае.


--------------------
Пишите в личку.
Go to the top of the page
 
+Quote Post
Dog Pawlowa
сообщение Dec 18 2006, 20:31
Сообщение #20


Гуру
******

Группа: Свой
Сообщений: 2 702
Регистрация: 14-07-06
Пользователь №: 18 823



Цитата(Oldring @ Dec 18 2006, 19:38) *
Ответ прост. До тех пор, пока результат вычисления всего целочисленного выражения не отличается от стандартного способа вычисления с учетом того, что при переполнении промежуточных результатов возможно undefined поведение, компилятор может делать все, что угодно. Но только пока не отличается. Более того, важен даже не результат вычисления одного выражения, а последовательность записи значений в volatile переменные и вызовов системных функций. Все оптимизации программы, которые сохраняют запись в volatile переменные и ызовы системных функций - законные, все, которые приводят к изменению внешнего поведения программы - незаконны.

Меня "правильность" компилятора мало интересует, я не д-р Туамосец.
Я рассматриваю правильность как максимально близкий результат к результату при перемножении в столбик smile.gif
И получается такая незадача, что правильность зависит от значения переменных.
int a,b,c;
a*b/c при a=100, b=100, c=3 правильно будет (a*cool.gif/c,
а при a=1000, b=1000, c=100 правильно будет a*(b/c).
Поэтому весь этот дискуссион не имеет смысла, тем более что автор не указал даже с какими числами он работал и предусмотрен ли запас по диапазону. Потому и залег на дно, видимо, предоставив нам возможность друг друга за чубы тягать smile.gif




Цитата(Oldring @ Dec 18 2006, 20:08) *
3. Нет. Компилятор обязан сделать чтобы снаружи выглядело как ему написали в любом случае.

Хм... Например, оптимизатор IAR самостоятельно заменяет switch (a) {case ....} на vector[a] и создает массив функций при большом числе a.
Такое решение выглядит, как написали, или не выглядит?


--------------------
Уходя, оставьте свет...
Go to the top of the page
 
+Quote Post
Oldring
сообщение Dec 18 2006, 20:37
Сообщение #21


Гуру
******

Группа: Свой
Сообщений: 3 041
Регистрация: 10-01-05
Из: Москва
Пользователь №: 1 874



Цитата(Dog Pawlowa @ Dec 18 2006, 20:23) *
Меня "правильность" компилятора мало интересует, я не д-р Туамосец.


Очень зря. Язык программирования - это стройная логическая система. К вычислению в столбик имеющая опосредованное отношение. Не без дыр, но когда дыры обнаруживают - их в комитете по стандартизации языка стараются закрыть в очередной редакции стандарта. Понимание внутреннего устройства языка позволяет избегать глубых ошибок и получать надежно работающую программу. Но такое понимание может дать только чтение формального стандарта.


Цитата(Dog Pawlowa @ Dec 18 2006, 20:31) *
Хм... Например, оптимизатор IAR самостоятельно заменяет switch (a) {case ....} на vector[a] и создает массив функций при большом числе a.
Такое решение выглядит, как написали, или не выглядит?


Раз такое преобразование не изменяет порядок вызова системных функций и обращений к volatile переменным - это совершенно законное преобразование программы.


--------------------
Пишите в личку.
Go to the top of the page
 
+Quote Post
prottoss
сообщение Dec 18 2006, 20:43
Сообщение #22


Гуру
******

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



Цитата(Dog Pawlowa @ Dec 19 2006, 00:31) *
И получается такая незадача, что правильность зависит от значения переменных.
int a,b,c;
a*b/c при a=100, b=100, c=3 правильно будет (a* cool.gif /c,
а при a=1000, b=1000, c=100 правильно будет a*(b/c).
Поэтому весь этот дискуссион не имеет смысла, тем более что автор не указал даже с какими числами он работал и предусмотрен ли запас по диапазону. Потому и залег на дно, видимо, предоставив нам возможность друг друга за чубы тягать smile.gif
Вы специально со скобками дуру гоните, али как? Выражаясь Вашими формулами вопрос задаем так - ПОЧЕМУ:



Global_Value = a * b / c отличается от Local_Value = a * b / c;



Скобки и привидения к типам в обоих равенствах можете расставить по собственному усмотрению и вкусу, НО одинаково



Цитата(Dog Pawlowa @ Dec 19 2006, 00:31) *
Цитата(Oldring @ Dec 18 2006, 20:08) *

3. Нет. Компилятор обязан сделать чтобы снаружи выглядело как ему написали в любом случае.

Хм... Например, оптимизатор IAR самостоятельно заменяет switch (a) {case ....} на vector[a] и создает массив функций при большом числе a.
Такое решение выглядит, как написали, или не выглядит?
Как раз подходит под то, что говорит Oldring - снаружи функции и со switch (a) {case ....} и с vector[a] будет выглядеть одинаково, здесь же мы наблюдаем "не одинаково"


--------------------
Go to the top of the page
 
+Quote Post
Oldring
сообщение Dec 18 2006, 21:14
Сообщение #23


Гуру
******

Группа: Свой
Сообщений: 3 041
Регистрация: 10-01-05
Из: Москва
Пользователь №: 1 874



Цитата(prottoss @ Dec 18 2006, 20:43) *
Выражаясь Вашими формулами вопрос задаем так - ПОЧЕМУ:



Global_Value = a * b / c отличается от Local_Value = a * b / c;



Скобки и привидения к типам в обоих равенствах можете расставить по собственному усмотрению и вкусу, НО одинаково


Да все что угодно может быть. Например из-за переполнения при вычислении выражения поведение оказалось неопределенным. Или результат используется каким-то специальным образом, компилятор это заметил - и соптимизировал. Листинг нужно смотреть, что там получается реально.


--------------------
Пишите в личку.
Go to the top of the page
 
+Quote Post
singlskv
сообщение Dec 18 2006, 21:18
Сообщение #24


дятел
*****

Группа: Свой
Сообщений: 1 681
Регистрация: 13-05-06
Из: Питер
Пользователь №: 17 065



Цитата(prottoss @ Dec 18 2006, 20:43) *
Выражаясь Вашими формулами вопрос задаем так - ПОЧЕМУ:

Global_Value = a * b / c отличается от Local_Value = a * b / c;

Автор топика так и не сказал, эта ошибка в "железе" или в симуляторе AVR Studio
Если в AVR Studio по Watch, то тогда надо пробовать так:
Global_Value1 = a * b / c;
Local_Value = a * b / c;
Global_Value2 = Local_Value;

и вот если не совпадут Global_Value1 и Global_Value2 то, тогда да, проблемма компиляции,
а если совпадут, то тогда все в порядке, оптимизатор поработал blink.gif
Go to the top of the page
 
+Quote Post
Dog Pawlowa
сообщение Dec 19 2006, 09:49
Сообщение #25


Гуру
******

Группа: Свой
Сообщений: 2 702
Регистрация: 14-07-06
Пользователь №: 18 823



Цитата(prottoss @ Dec 18 2006, 20:43) *
Вы специально со скобками дуру гоните, али как? Выражаясь Вашими формулами вопрос задаем так - ПОЧЕМУ:
Global_Value = a * b / c отличается от Local_Value = a * b / c;
Скобки и привидения к типам в обоих равенствах можете расставить по собственному усмотрению и вкусу, НО одинаково

Дуру? Отчасти smile.gif
А на конкретный вопрос - конкретный ответ :

Да, сравнивать Global_Value = a * b / c и Local_Value = a * b / c при int a,b,c считаю некорректным.

Но можно сравнивать Global_Value = a * (b / c) и Local_Value = a *( b / c)
Или Global_Value = (long) a * (long) b / c и Local_Value = (long)a *(long) b / c, а еще лучше
Global_Value = ((long) a * (long) b ) / c и Local_Value = ((long)a *(long) b ) / c
И только после этого может появиться предположение об "ошибке".
У меня один и тот же проект постоянно портируется с MS VC на IAR AVR и обратно, да, было пару выбрыков у ИАРа, но в целом это вполне нормальный инструмент. За приемлемую цену wink.gif

Все, пока автор не появится - ни строчки.

Сообщение отредактировал Dog Pawlowa - Dec 19 2006, 09:54


--------------------
Уходя, оставьте свет...
Go to the top of the page
 
+Quote Post
Sergio66
сообщение Dec 19 2006, 11:57
Сообщение #26


Местный
***

Группа: Свой
Сообщений: 235
Регистрация: 9-02-05
Пользователь №: 2 526



[/quote]
Дуру? Отчасти smile.gif
А на конкретный вопрос - конкретный ответ :

Да, сравнивать Global_Value = a * b / c и Local_Value = a * b / c при int a,b,c считаю некорректным.

Но можно сравнивать Global_Value = a * (b / c) и Local_Value = a *( b / c)
Или Global_Value = (long) a * (long) b / c и Local_Value = (long)a *(long) b / c, а еще лучше
Global_Value = ((long) a * (long) b ) / c и Local_Value = ((long)a *(long) b ) / c
И только после этого может появиться предположение об "ошибке".
У меня один и тот же проект постоянно портируется с MS VC на IAR AVR и обратно, да, было пару выбрыков у ИАРа, но в целом это вполне нормальный инструмент. За приемлемую цену wink.gif

Все, пока автор не появится - ни строчки.
[/quote]

Вот и автор.
Итак, что касается значения переменных. В приведенном случае:
data_temp_struct.temp = INJ_time * data_temp_struct.FREQ * PRODUCTIVITY / 20000;
long int INJ_time = от 74 000 до 75 000
unsigned int data_temp_struct.FREQ = 1000 (задается в процессе эксперимента)
PRODUCTIVITY = 5 (в данном случае)
long int Local_Value temp = INJ_time * data_temp_struct.FREQ * PRODUCTIVITY / 20000;
где long int Local_Value размещена в регистрах
в результате дает непонятное случайное число
заменив переменную temp на data_temp_struct.temp я добился того, что она теперь размещена в памяти. При этом все вычисления пошли верно.
Теперь о свертывании констант - как вы можете видеть, PRODUCTIVITY (=5)/ 20000 корректно никак свернуто быть не может (при данных значениях)

Был проделан сл эксперимент - формула была упрощена до вида:
long int Local_Value temp = INJ_time * PRODUCTIVITY;
И только...
Результат был неверным! Только размещение в памяти результирующей переменной дало эффект!!!
Т.о. у меня есть 2 подозрения -
1. глюк компиллятора
2. Коллизия с распределением памяти. Возможно стек возвратов, возможно стек данных.
Многие глюки у меня решались именно изменением этих параметров. Правда, в данном случае мне не удалось подобрать ничего правильного.
Дело в том, что проект очень большой порядка 10 000 строк. Большой расход памяти, задействованы почти все мыслимые и немыслимые аппаратные ресурсы и прерывания.
Возможно, компиллятор столкнулся с какими то внутренними проблемами при обработке такого сложного проекта.
Кстати, оптимизацию я полностью отключал. На это грешить не приходится.

Вот такие дела!
Go to the top of the page
 
+Quote Post
GDI
сообщение Dec 19 2006, 13:32
Сообщение #27


Профессионал
*****

Группа: Свой
Сообщений: 1 235
Регистрация: 14-05-05
Из: Санкт-Петербург
Пользователь №: 5 008



Была у меня похожая проблема, правда, у меня портилась переменная типа char, которая была счетчиком внутри функции, при пошаговом выполнении программы в АВР-Студио выяснилось, что эта переменная размешена в регистре и при вызове вложенной подпрограммы этот регистр портился внутри этой подпрограммы, соответственно при возврате из подпрограммы мой счетчик приобретал не правильное значение.. в моем случае проблема была решена путем объявления переменной как static char, после этого она была размещена в памяти данных, а не в регистре и проблемы больше не возникало.


--------------------
http://www.embedders.org Блоги разработчиков электроники.
Go to the top of the page
 
+Quote Post
Oldring
сообщение Dec 19 2006, 14:44
Сообщение #28


Гуру
******

Группа: Свой
Сообщений: 3 041
Регистрация: 10-01-05
Из: Москва
Пользователь №: 1 874



Цитата(Sergio66 @ Dec 19 2006, 11:57) *
Результат был неверным! Только размещение в памяти результирующей переменной дало эффект!!!


Так сразу после вычисленя выражения в регистрах результат правильный?

Ошибки компилятора, конечно, встречаются - но в 90% случаев подозрения на ошибки компилятора не оправдываются, оказываясь ошибками программиста. Поэтому утверждение про ошибку компилятора требуют более серьезных аргументов, чем "написал так - не работает, написал иначе - работает".


--------------------
Пишите в личку.
Go to the top of the page
 
+Quote Post
Sergio66
сообщение Dec 19 2006, 15:15
Сообщение #29


Местный
***

Группа: Свой
Сообщений: 235
Регистрация: 9-02-05
Пользователь №: 2 526



Цитата(Oldring @ Dec 19 2006, 15:44) *
Цитата(Sergio66 @ Dec 19 2006, 11:57) *

Результат был неверным! Только размещение в памяти результирующей переменной дало эффект!!!


Так сразу после вычисленя выражения в регистрах результат правильный?

Ошибки компилятора, конечно, встречаются - но в 90% случаев подозрения на ошибки компилятора не оправдываются, оказываясь ошибками программиста. Поэтому утверждение про ошибку компилятора требуют более серьезных аргументов, чем "написал так - не работает, написал иначе - работает".


Да нет же! Пока я не переразместил переменную, все считалось неверно. И в регистрах был неверный результат.
Go to the top of the page
 
+Quote Post
Dog Pawlowa
сообщение Dec 19 2006, 19:10
Сообщение #30


Гуру
******

Группа: Свой
Сообщений: 2 702
Регистрация: 14-07-06
Пользователь №: 18 823



Цитата(Sergio66 @ Dec 19 2006, 15:15) *
Да нет же! Пока я не переразместил переменную, все считалось неверно. И в регистрах был неверный результат.

Тот самый случай, когда лучше один раз увидеть, чем сто раз услышать.
А еще лучше совсем не видеть :-)
Я вот недавно буфер для sprintf малый сделал, и пол-дня искал причину затирания переменной, все ошибки в компиляторе искал и стек считал...
Нет? biggrin.gif


--------------------
Уходя, оставьте свет...
Go to the top of the page
 
+Quote Post

5 страниц V  < 1 2 3 4 > » 
Reply to this topicStart new topic
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0

 


RSS Текстовая версия Сейчас: 18th July 2025 - 15:06
Рейтинг@Mail.ru


Страница сгенерированна за 0.02259 секунд с 7
ELECTRONIX ©2004-2016