Перейти к содержанию
    

IAR 5.40.0.51500 баг в sprintf @ lpc1114/CM0

Непонятный баг в виде выпадения в HardFault из sprintf при выводе форматированного float, причём в некоторых случаях. Юзал эту версию ИАРа вместе со sprintf для LPC1768 и ни на какие грабли не попадал. Стек проверял, его достаточно, оптимизация никак не влияет. Простенький кастрированный проект прилагаю для LPC1114 (без кварца) можно потестить. Прочитал все исправленные баги в версии 6.30 и не нашёл ничего об исправленном sprintf. Хотя тот же код в 6.30 не зависает, но проверил наспех. Поэтому самому интересно в чём косяк и исправлен ли он в новых версиях ИАРа.

 

    sprintf((char *)&buf, "started\15\12");
    sendBuf(&buf[0]);

    for (uInt i=0; i<sizeof(buf); ++i) buf[i] = 0xeb;
    float freq = 82.6046981;
    sprint_flag = 10;
    sprintf((char *)&buf, "freq1=%1.5f\15\12", freq);           // <------- тут происходит падение на HardFault
    sprint_flag = 0;
    sendBuf(&buf[0]);

    sprintf((char *)&buf, "ended\15\12");
    sendBuf(&buf[0]);

 

Регистры на картинке взяты из режима исключения HardFault, на котором стоит бесконечный цикл.

post-16753-1362527194_thumb.png

post-16753-1362527209_thumb.png

post-16753-1362527217_thumb.png

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Это что такое и с чем его едят?

Вообще-то я ничего с этой опцией не делал. Если по-умолчанию проц её держит в неправильном состоянии, то это ненормально. При выводе многих других значений float, например 0.0 всё работает отлично.

 

-----------

 

Упд.

Посмотрел в мануале на LPC111x. Регистр с этой опцией - RO, то бишь не меняется и бит этот всегда установлен.

Изменено пользователем GetSmart

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Это что такое и с чем его едят?

Битик в Configuration Control Register, включающий abort при любом невыровненном доступе.

По умолчанию выключен, разумеется. В дизассемблере криминала нет, кроме упомянутого доступа.

Так что проверьте.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Если буфер (buf) является массивом, то char-указатель на него записывается так:

(char *)buf

а не так:

(char *)&buf

 

А если же автор программы хочет обязательно куда-то вставить значок &, то пусть пишет:

(char *)&buf[0]

и это будет правильно.

 

Т.е. во всех функциях sprintf в качестве 1-го аргумента следует указывать (char *)buf или (char *)&buf[0], а не (char *)&buf

А покуда это не сделано, искать какие-то иные ошибки в его коде неразумно.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Стоп, это ж M0, а он в принципе не умеет unaligned access делать.

В опциях точно M0 стоит? Если да, тогда баг однозначно.

 

Т.е. во всех функциях sprintf в качестве 1-го аргумента следует указывать (char *)buf или (char *)&buf[0], а не (char *)&buf

А покуда это не сделано, искать какие-то иные ошибки в его коде неразумно.

В случае массива buf и &buf - это одно и то же.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

В случае массива buf и &buf - это одно и то же.

 

Только в тех случаях, когда массив статический, да и то взависимости от реализации компилятора. В случаях, когда массив выделяется динамически, вы не правы во всех отношениях.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

ОК, согласен. Но в данном конкретном случае это к проблеме ни малейшего отношения не имеет.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Попробуйте так:

sprintf((char *)buf, "freq1=%1.5f\15\12", (double)freq);

Т.е. приведите аргумент freq к double.

Да, и стек должен быть на 8 выровнен (по крайней мере для CM3 это обязательно).

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Стоп, это ж M0, а он в принципе не умеет unaligned access делать.

В опциях точно M0 стоит? Если да, тогда баг однозначно.

Да, точно М0.

Мне во всём этом интересно, что баг этот зависит от стечения многих нюансов. Например формата %1.5 в сочетании с float. Поэтому и приводить к double смысла нет. Там с тем значением плавучки идёт округление двух чисел и результат сокращается до 4 знаков после запятой. Может это что-то значит. Вообще, хотелось бы выяснить задокументирован этот баг или нет. И связь с новыми версиями компиляторов.

 

Почему, кстати, у многих местных модераторов есть такая привычка делать несущественные замечания. Зелтиго, Резидент, Ксюша, все страдают этим. Зелтиго в отсутствие аргументов вообще любит/л цепляться за while(1). Если конструктивно нечего сказать, то лучше промолчать. ИМХО это "болезнь", корелирующая с некой административной профнепригодностью.

 

В том конкретном случае &buf и &buf[0] абсолютно одинаковый код дают, т.к. буфер статический с абсолютным адресом. Меняй, не меняй каша слаще не станет.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Да, точно М0.

Мне во всём этом интересно, что баг этот зависит от стечения многих нюансов. Например формата %1.5 в сочетании с float. Поэтому и приводить к double смысла нет.

 

Почему, кстати, у многих местных модераторов есть такая привычка делать несущественные замечания. Зелтиго, Резидент, Ксюша, все страдают этим. Зелтиго в отсутствие аргументов вообще любит/л цепляться за while(1). Если конструктивно нечего сказать, то лучше промолчать. ИМХО это "болезнь", корелирующая с некой административной профнепригодностью.

 

В том конкретном случае &buf и &buf[0] абсолютно одинаковый код дают, т.к. буфер статический с абсолютным адресом. Меняй, не меняй каша слаще не станет.

Мдя.

Зачем вы вообще совета просите, если не хотите хотя бы проверить его.

Почитайте стандарт С.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Стоп, это ж M0, а он в принципе не умеет unaligned access делать.

Ну а допустим это был бы СМ3 со сброшенным битом UNALIGN_TRP. Он ведь всё-равно не так сохранил бы в память как умеет х86? То бишь прога не зависла бы, но значение неправильное бы выводила? Начинаю сомневаться за свои проекты, работающие в 5.40 для СМ3.

 

Мдя.

Зачем вы вообще совета просите, если не хотите хотя бы проверить его.

Почитайте стандарт С.

Прочитал. Исправил. Ничего не изменилось. Вам полегчало? Ведь это было изначально очевидно, что дело не в этом. Даже напрягаться не надо было на написание сообщений. К вам это не относится, но есть такая вещь: кто умеет - помогает, кто не умеет - цепляется. Уметь видеть нечёткое несоответствие стандарту, которое не влияет на кодогенерацию - гораздо полезнее, чем просто видеть несоответствие стандарту. Если дотошно разбирать первоначальный код, то он абсолютно верный по стандарту. Не универсальный, но верный в конкретном случае, учитывая рядом стоящее описание переменной buf. Доказывается это просто, вручную выполняя однозначный анализ компилятора. Поэтому даже отсылка в чтение стандарта является слишком безапеляционной. По поводу дабла - смысл не в том, чтобы как-нибудь обойти этот баг, а точно выяснить может ли он при каких-нибудь условиях и каких-нибудь параметрах функции появляться. Ну и конечно разобраться чей это баг.

 

По поводу выравнивания на 8 "внутри кода" (ака перед вызовом sprintf) - это очень непонятная мне вещь. Зачем оно? То, что внутри скрипта линкера должно быть выравнивание на 8, это есть.

Изменено пользователем GetSmart

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

А какая версия printf стоит в настройках проекта? Помню что small точно не работает с флоатом, то есть символ %f просто не раскручивается, но возможно в реализации либы для М0 там баг и все падает :) Попробуйте поставить full.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Ну а допустим это был бы СМ3 со сброшенным битом UNALIGN_TRP. Он ведь всё-равно не так сохранил бы в память как умеет х86? То бишь прога не зависла бы, но значение неправильное бы выводила? Начинаю сомневаться за свои проекты, работающие в 5.40 для СМ3.

Нет, M3 бы отработал правильно, сохранил "как x86". В отличие от M0 он умеет.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Попробуйте поставить full.

Такая и стоит. Иначе бы он вообще никакие значения плавучки не отображал. А он отображает, когда не виснет.

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Присоединяйтесь к обсуждению

Вы можете написать сейчас и зарегистрироваться позже. Если у вас есть аккаунт, авторизуйтесь, чтобы опубликовать от имени своего аккаунта.

Гость
Ответить в этой теме...

×   Вставлено с форматированием.   Вставить как обычный текст

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отображать как обычную ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.

×
×
  • Создать...