Jump to content

    
Sign in to follow this  
GetSmart

IAR 5.40.0.51500 баг в sprintf @ lpc1114/CM0

Recommended Posts

Непонятный баг в виде выпадения в 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

Share this post


Link to post
Share on other sites

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

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

 

-----------

 

Упд.

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

Edited by GetSmart

Share this post


Link to post
Share on other sites
Это что такое и с чем его едят?

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

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

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

Share this post


Link to post
Share on other sites

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

(char *)buf

а не так:

(char *)&buf

 

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

(char *)&buf[0]

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

 

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

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

Share this post


Link to post
Share on other sites

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

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

 

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

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

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

Share this post


Link to post
Share on other sites
В случае массива buf и &buf - это одно и то же.

 

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

Share this post


Link to post
Share on other sites

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

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

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

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

Share this post


Link to post
Share on other sites
Стоп, это ж M0, а он в принципе не умеет unaligned access делать.

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

Да, точно М0.

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

 

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

 

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

Share this post


Link to post
Share on other sites
Да, точно М0.

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

 

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

 

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

Мдя.

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

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

Share this post


Link to post
Share on other sites
Стоп, это ж M0, а он в принципе не умеет unaligned access делать.

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

 

Мдя.

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

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

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

 

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

Edited by GetSmart

Share this post


Link to post
Share on other sites

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

Share this post


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

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

Share this post


Link to post
Share on other sites
Попробуйте поставить full.

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

 

Share this post


Link to post
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Sign in to follow this