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

 
 
> Применение буферов больше 256 байт глючит sprintf, Камень stm32L476
Димон Безпарольн...
сообщение Aug 22 2017, 19:19
Сообщение #1


Знающий
****

Группа: Участник
Сообщений: 734
Регистрация: 29-11-10
Пользователь №: 61 247



Почему при использовании буферов (у меня их 4) в разных местах размером больше 256 (ставил 400) начинает рассыпаться sprintf - выводит глюки.

В чем может быть проблема?
Go to the top of the page
 
+Quote Post
3 страниц V   1 2 3 >  
Start new topic
Ответов (1 - 37)
x893
сообщение Aug 22 2017, 19:23
Сообщение #2


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

Группа: Свой
Сообщений: 1 333
Регистрация: 27-10-08
Из: Планета Земля
Пользователь №: 41 226



Это ЧУДО !
Go to the top of the page
 
+Quote Post
Димон Безпарольн...
сообщение Aug 22 2017, 19:59
Сообщение #3


Знающий
****

Группа: Участник
Сообщений: 734
Регистрация: 29-11-10
Пользователь №: 61 247



Чисто поржать - мне не до смеха. Есть какая специфика использования таких буферов?
Go to the top of the page
 
+Quote Post
Lagman
сообщение Aug 22 2017, 20:01
Сообщение #4


Знающий
****

Группа: Свой
Сообщений: 875
Регистрация: 28-10-05
Пользователь №: 10 245



а буфер наверно объявлен как char с размером [0xff] и подаете вы туда utf8 sm.gif
Go to the top of the page
 
+Quote Post
Димон Безпарольн...
сообщение Aug 22 2017, 20:03
Сообщение #5


Знающий
****

Группа: Участник
Сообщений: 734
Регистрация: 29-11-10
Пользователь №: 61 247



Цитата(Lagman @ Aug 23 2017, 00:01) *
а буфер наверно объявлен как char с размером [0xff] и подаете вы туда utf8 sm.gif

Вовсе нет.

Буфер char buf[400]; и подаю я туда байты.
Go to the top of the page
 
+Quote Post
aaarrr
сообщение Aug 22 2017, 20:09
Сообщение #6


Гуру
******

Группа: Свой
Сообщений: 10 713
Регистрация: 11-12-04
Пользователь №: 1 448



Цитата(Димон Безпарольный @ Aug 22 2017, 22:59) *
Есть какая специфика использования таких буферов?

Никакой. Накладываются, наверно, буферы на стек - и привет.
Go to the top of the page
 
+Quote Post
jcxz
сообщение Aug 22 2017, 20:42
Сообщение #7


Гуру
******

Группа: Свой
Сообщений: 5 228
Регистрация: 3-07-08
Из: Омск
Пользователь №: 38 713



Цитата(Димон Безпарольный @ Aug 22 2017, 22:59) *
Чисто поржать - мне не до смеха. Есть какая специфика использования таких буферов?

Вероятных причин может быть целая туча. А реальная вряд-ли связана со sprintf. Скорее баг у вас в другом месте.
Например: каков размера стека задачи, вызывающей sprintf?

PS: Не использую sprintf ни в одном из последних проектов....
Go to the top of the page
 
+Quote Post
Димон Безпарольн...
сообщение Aug 22 2017, 20:44
Сообщение #8


Знающий
****

Группа: Участник
Сообщений: 734
Регистрация: 29-11-10
Пользователь №: 61 247



Цитата(jcxz @ Aug 23 2017, 00:42) *
Например: каков размера стека задачи, вызывающей sprintf?

Как это узнать?
Go to the top of the page
 
+Quote Post
aaarrr
сообщение Aug 22 2017, 21:06
Сообщение #9


Гуру
******

Группа: Свой
Сообщений: 10 713
Регистрация: 11-12-04
Пользователь №: 1 448



Цитата(Димон Безпарольный @ Aug 22 2017, 23:44) *
Как это узнать?

Традиционный способ такой:
1. Заполняем выделенную под стек память каким-нибудь паттерном (хоть бы и однобайтовым)
2. Вызываем интересующую процедуру
3. Смотрим, сколько памяти было "затерто"
Go to the top of the page
 
+Quote Post
jcxz
сообщение Aug 22 2017, 21:18
Сообщение #10


Гуру
******

Группа: Свой
Сообщений: 5 228
Регистрация: 3-07-08
Из: Омск
Пользователь №: 38 713



Цитата(Димон Безпарольный @ Aug 22 2017, 23:44) *
Как это узнать?

Это надо не узнавать. А задавать. У себя в исходниках. Если конечно писали их Вы....

Цитата(aaarrr @ Aug 23 2017, 00:06) *
3. Смотрим, сколько памяти было "затерто"

В некоторых случаях наблюдал как ..printf из IAR-овской библиотеки использовал до немного больше 256 байт стека.
Но это не при каждом вызове. Обычно - намного меньше. Так что "просто вызвать и посмотреть сколько потрёт" - тут не всегда сработает как надо.
Go to the top of the page
 
+Quote Post
Димон Безпарольн...
сообщение Aug 22 2017, 21:20
Сообщение #11


Знающий
****

Группа: Участник
Сообщений: 734
Регистрация: 29-11-10
Пользователь №: 61 247



Цитата(aaarrr @ Aug 23 2017, 01:06) *
Традиционный способ такой:
1. Заполняем выделенную под стек память каким-нибудь паттерном (хоть бы и однобайтовым)
2. Вызываем интересующую процедуру
3. Смотрим, сколько памяти было "затерто"

Слишком сложно.

Даже если смогу, как изменить размер?
Go to the top of the page
 
+Quote Post
aaarrr
сообщение Aug 22 2017, 21:29
Сообщение #12


Гуру
******

Группа: Свой
Сообщений: 10 713
Регистрация: 11-12-04
Пользователь №: 1 448



Цитата(jcxz @ Aug 23 2017, 00:18) *
В некоторых случаях наблюдал как ..printf из IAR-овской библиотеки использовал до немного больше 256 байт стека.
Но это не при каждом вызове. Обычно - намного меньше. Так что "просто вызвать и посмотреть сколько потрёт" - тут не всегда сработает как надо.

Да форматированный ввод-вывод очень прожорлив. Смотреть, естественно, наиболее навороченные вызовы.

Цитата(Димон Безпарольный @ Aug 23 2017, 00:20) *
Слишком сложно.

Несколько строк кода.

Цитата(Димон Безпарольный @ Aug 23 2017, 00:20) *
Даже если смогу, как изменить размер?

Этот момент лучше выяснять задолго до введения нескольких буферов по 400 байт.

Кстати,
Цитата(Димон Безпарольный @ Aug 22 2017, 23:03) *
Буфер char buf[400]; и подаю я туда байты.

buf - не локальный часом?
Go to the top of the page
 
+Quote Post
Димон Безпарольн...
сообщение Aug 22 2017, 21:30
Сообщение #13


Знающий
****

Группа: Участник
Сообщений: 734
Регистрация: 29-11-10
Пользователь №: 61 247



Цитата(aaarrr @ Aug 23 2017, 01:29) *
buf - не локальный часом?

Локальный. А что?
Go to the top of the page
 
+Quote Post
jcxz
сообщение Aug 22 2017, 21:33
Сообщение #14


Гуру
******

Группа: Свой
Сообщений: 5 228
Регистрация: 3-07-08
Из: Омск
Пользователь №: 38 713



Цитата(aaarrr @ Aug 23 2017, 00:29) *
Цитата(Димон Безпарольный @ Aug 22 2017, 23:03) *

Буфер char buf[400]; и подаю я туда байты.

buf - не локальный часом?

biggrin.gif

Это надо уже заносить в faq для чайников.
Go to the top of the page
 
+Quote Post
Димон Безпарольн...
сообщение Aug 22 2017, 21:36
Сообщение #15


Знающий
****

Группа: Участник
Сообщений: 734
Регистрация: 29-11-10
Пользователь №: 61 247



Полагаю есть ограничение? Уж не 255 ли?
Go to the top of the page
 
+Quote Post
aaarrr
сообщение Aug 22 2017, 21:41
Сообщение #16


Гуру
******

Группа: Свой
Сообщений: 10 713
Регистрация: 11-12-04
Пользователь №: 1 448



Цитата(Димон Безпарольный @ Aug 23 2017, 00:36) *
Полагаю есть ограничение? Уж не 255 ли?

Локальный буфер выделяется на стеке, еще здоровый кусок от него может откусить sprintf.
Ограничение определяется размером стека и только.
Go to the top of the page
 
+Quote Post
Димон Безпарольн...
сообщение Aug 22 2017, 21:43
Сообщение #17


Знающий
****

Группа: Участник
Сообщений: 734
Регистрация: 29-11-10
Пользователь №: 61 247



Цитата(aaarrr @ Aug 23 2017, 01:41) *
Локальный буфер выделяется на стеке, еще здоровый кусок от него может откусить sprintf.
Ограничение определяется размером стека и только.

Похоже. У меня в sprintf строка в 290байт. Как это ограничение обойти?

Сообщение отредактировал Димон Безпарольный - Aug 22 2017, 21:44
Go to the top of the page
 
+Quote Post
aaarrr
сообщение Aug 22 2017, 22:02
Сообщение #18


Гуру
******

Группа: Свой
Сообщений: 10 713
Регистрация: 11-12-04
Пользователь №: 1 448



Цитата(Димон Безпарольный @ Aug 23 2017, 00:43) *
Похоже. У меня в sprintf строка в 290байт. Как это ограничение обойти?

1. Увеличить размер стека

И еще постараться:
2. Не держать локальные буферы по полкилобайта
3. Не формировать sprintf'ом строки по 290 байт

Это весьма расточительно, если всей памяти десятки килобайт.
Go to the top of the page
 
+Quote Post
Димон Безпарольн...
сообщение Aug 22 2017, 22:11
Сообщение #19


Знающий
****

Группа: Участник
Сообщений: 734
Регистрация: 29-11-10
Пользователь №: 61 247



1. Буду благодарен если намекнете как.

2,3 Что делать если надо сформировать строку:

Цитата
{ "d" : {"deviceid":"<deviceid>","param5":"<dw>","param6":"<fullw> ",”param7”:”<kk>”,”param8”:”<diff>”,”param9”:”<maxt>” ,”param11”:”<mint>”,”param12”:”<msisdn>”,”param13”:”<imei>”,”param14”:”<mac>”,”param15”:”<ccid>”,”param16”:”<rmod>”,”param17”:”<ssid>”,”param18”:”<lin>”,,”param19”:”<uptime>”}}


Бред конечно - но не я диктую моду...
Go to the top of the page
 
+Quote Post
aaarrr
сообщение Aug 22 2017, 22:53
Сообщение #20


Гуру
******

Группа: Свой
Сообщений: 10 713
Регистрация: 11-12-04
Пользователь №: 1 448



Цитата(Димон Безпарольный @ Aug 23 2017, 01:11) *
1. Буду благодарен если намекнете как.

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

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

Димон, складывается впечатление, что вы пытаетесь собрать что-то монструозное,
но при этом стараетесь обходить стороной фундаментальные основы. Не получится так sad.gif

Цитата(Димон Безпарольный @ Aug 23 2017, 01:11) *
2,3 Что делать если надо сформировать строку:

Разделить её на кучу мелких по числу param.
Go to the top of the page
 
+Quote Post
jcxz
сообщение Aug 22 2017, 23:00
Сообщение #21


Гуру
******

Группа: Свой
Сообщений: 5 228
Регистрация: 3-07-08
Из: Омск
Пользователь №: 38 713



Цитата(Димон Безпарольный @ Aug 23 2017, 01:11) *
2,3 Что делать если надо сформировать строку:

Надо начать с вопроса: "А зачем её формировать в этом буфере"? И можно ли без этого обойтись?
Я вот тоже сейчас например в текущем проекте распарсиваю и формирую "модные" JSON-сообщения в несколько кБ (а возможно вырастут до сотен кБ), обходясь буферами в десятки-сотни байт. Без каких-либо проблем.
Go to the top of the page
 
+Quote Post
Димон Безпарольн...
сообщение Aug 23 2017, 05:29
Сообщение #22


Знающий
****

Группа: Участник
Сообщений: 734
Регистрация: 29-11-10
Пользователь №: 61 247



Цитата(jcxz @ Aug 23 2017, 03:00) *
Надо начать с вопроса: "А зачем её формировать в этом буфере"? И можно ли без этого обойтись?
Я вот тоже сейчас например в текущем проекте распарсиваю и формирую "модные" JSON-сообщения в несколько кБ (а возможно вырастут до сотен кБ), обходясь буферами в десятки-сотни байт. Без каких-либо проблем.

Парсить можно разбивая строку. Но это отправляемая строка. Она целиком должна быть запихнута в сериализатор и далее на отправку. Представить не могу как частями это сделать.

Заказчик очень хочет чтобы эта кишка не разбивалась.
Go to the top of the page
 
+Quote Post
aaarrr
сообщение Aug 23 2017, 05:48
Сообщение #23


Гуру
******

Группа: Свой
Сообщений: 10 713
Регистрация: 11-12-04
Пользователь №: 1 448



Заполнять буфер тоже можно частями. Посмотрите, что возвращает функция sprintf.
Go to the top of the page
 
+Quote Post
Димон Безпарольн...
сообщение Aug 23 2017, 06:04
Сообщение #24


Знающий
****

Группа: Участник
Сообщений: 734
Регистрация: 29-11-10
Пользователь №: 61 247



Цитата(aaarrr @ Aug 23 2017, 09:48) *
Заполнять буфер тоже можно частями. Посмотрите, что возвращает функция sprintf.

Согласен. Но буфер должен быть единым. Т.е. больше 256 байт. И локальным его не удается пока сделать. Сделал в лоб - объявил глобальным. Работает. Но не нравится нагрузка на память.
Go to the top of the page
 
+Quote Post
aaarrr
сообщение Aug 23 2017, 06:31
Сообщение #25


Гуру
******

Группа: Свой
Сообщений: 10 713
Регистрация: 11-12-04
Пользователь №: 1 448



Цитата(Димон Безпарольный @ Aug 23 2017, 09:04) *
...локальным его не удается пока сделать. Сделал в лоб - объявил глобальным. Работает. Но не нравится нагрузка на память.

Есть такая вещь, как динамическое выделение памяти. Но применять его пока не советую, нужно сначала со стеками разобраться.
Go to the top of the page
 
+Quote Post
jcxz
сообщение Aug 23 2017, 07:24
Сообщение #26


Гуру
******

Группа: Свой
Сообщений: 5 228
Регистрация: 3-07-08
Из: Омск
Пользователь №: 38 713



Цитата(Димон Безпарольный @ Aug 23 2017, 08:29) *
Парсить можно разбивая строку. Но это отправляемая строка. Она целиком должна быть запихнута в сериализатор и далее на отправку. Представить не могу как частями это сделать.

Вот точно так же можно и отправляемую строку по частям напечатать. Я именно так и делаю. Писал выше. У меня строки размером до десятка кБ (а будут много больше). И печатают они в Ethernet-кадры, размер которых 576 байт

Цитата(Димон Безпарольный @ Aug 23 2017, 09:04) *
Согласен. Но буфер должен быть единым. Т.е. больше 256 байт.

Нет. Если включить голову, то печатать можно окнами через тот же ..printf.
И кучу тоже не использую - печать сразу в Ethernet-кадры.
Go to the top of the page
 
+Quote Post
scifi
сообщение Aug 23 2017, 07:27
Сообщение #27


Гуру
******

Группа: Свой
Сообщений: 3 020
Регистрация: 7-02-07
Пользователь №: 25 136



Я правильно понял, что ТС не выяснил, сколько у него стека, и сколько его расходуется? И не планирует этим заниматься? Если так, помочь тут нечем, сушите вёсла.
Go to the top of the page
 
+Quote Post
Димон Безпарольн...
сообщение Aug 23 2017, 07:39
Сообщение #28


Знающий
****

Группа: Участник
Сообщений: 734
Регистрация: 29-11-10
Пользователь №: 61 247



Цитата(scifi @ Aug 23 2017, 11:27) *
Я правильно понял, что ТС не выяснил, сколько у него стека, и сколько его расходуется? И не планирует этим заниматься? Если так, помочь тут нечем, сушите вёсла.

Ковырялся. Пока не получилось. Методику ищу, изучаю. Не факт что осилю.

й
Цитата(jcxz @ Aug 23 2017, 11:24) *
И кучу тоже не использую - печать сразу в Ethernet-кадры.

Она сериализатором по частям не обрабатывается. Т.е. можно и свой сериализатор написать. Но боюсь времени не хватит.
Go to the top of the page
 
+Quote Post
Михась
сообщение Aug 23 2017, 13:12
Сообщение #29


Частый гость
**

Группа: Участник
Сообщений: 161
Регистрация: 29-09-10
Пользователь №: 59 816



Есть полезная штука по крайней мере у Кейла:
При компиляции опасные функции обрамляются ватермарком и при его повреждении - вызывается специальная функция.

http://www.keil.com/support/man/docs/armcc...59124940593.htm
Go to the top of the page
 
+Quote Post
Aleksandr Barano...
сообщение Aug 23 2017, 15:04
Сообщение #30


Частый гость
**

Группа: Участник
Сообщений: 169
Регистрация: 31-08-05
Из: New York
Пользователь №: 8 118



Если компилятор - IAR, то там есть встроенная функция контроля переполнения стека.


--------------------
ASB
Go to the top of the page
 
+Quote Post
Димон Безпарольн...
сообщение Aug 23 2017, 15:51
Сообщение #31


Знающий
****

Группа: Участник
Сообщений: 734
Регистрация: 29-11-10
Пользователь №: 61 247



Keil 5
Go to the top of the page
 
+Quote Post
Димон Безпарольн...
сообщение Aug 23 2017, 17:44
Сообщение #32


Знающий
****

Группа: Участник
Сообщений: 734
Регистрация: 29-11-10
Пользователь №: 61 247



Пытаюсь работать с ключом --protect_stack

Вставил функцию:

Код
void *__stack_chk_guard;


void __stack_chk_fail(void)
{
    
}


Но виснет при обращении к массивам.

Сообщение отредактировал Димон Безпарольный - Aug 23 2017, 17:45
Go to the top of the page
 
+Quote Post
jcxz
сообщение Aug 23 2017, 19:27
Сообщение #33


Гуру
******

Группа: Свой
Сообщений: 5 228
Регистрация: 3-07-08
Из: Омск
Пользователь №: 38 713



Цитата(Михась @ Aug 23 2017, 16:12) *
При компиляции опасные функции обрамляются ватермарком и при его повреждении - вызывается специальная функция.

Малоэффективно. Вот пример перед глазами - случай автора топика: выставили ватермарк на 200 ниже SP перед входом в функцию, а автор взял и выделил в функции 400, (т.е. - начало этого массива оказалось на 200 байт ниже ватермарка) и напечатал в этот буфер скажем 150 байт - ватермарк остался нетронутым, а стек переполнился и затёр соседние данные (или они его).
Да и куда ставить этот ватермарк, если автор даже не знает размера своего стека?? smile3009.gif
Go to the top of the page
 
+Quote Post
Михась
сообщение Aug 24 2017, 02:16
Сообщение #34


Частый гость
**

Группа: Участник
Сообщений: 161
Регистрация: 29-09-10
Пользователь №: 59 816



Цитата(jcxz @ Aug 24 2017, 01:27) *
Малоэффективно. Вот пример перед глазами - случай автора топика: выставили ватермарк на 200 ниже SP перед входом в функцию, а автор взял и выделил в функции 400, (т.е. - начало этого массива оказалось на 200 байт ниже ватермарка) и напечатал в этот буфер скажем 150 байт - ватермарк остался нетронутым, а стек переполнился и затёр соседние данные (или они его).


Эффективно как раз. У автора действительно тяжелый случай, но он явно выпаливается по внешним признакам. А --protect_stack как раз хорошо помогает, когда выделили для разных задач много маленьких буферов и потом в результате ошибки (не хватило пару байт потому что пролюбили пробел например) при печати в буфер портится соседнее значение, причем не каждый раз. И вот тут такое исключение чрезвычайно полезно. У меня раз такая ошибка в релизное ПО ушла. Одного чара в буфере не хватило.
Go to the top of the page
 
+Quote Post
Михась
сообщение Aug 24 2017, 05:57
Сообщение #35


Частый гость
**

Группа: Участник
Сообщений: 161
Регистрация: 29-09-10
Пользователь №: 59 816



Цитата(Димон Безпарольный @ Aug 24 2017, 00:44) *
Пытаюсь работать с ключом --protect_stack

Вставил функцию:

Код
void *__stack_chk_guard;


void __stack_chk_fail(void)
{
    
}


Но виснет при обращении к массивам.


Применяю так:

Цитата
void * __stack_chk_guard = (void *)(0xDEADBEEF);

void __stack_chk_fail(void)
{
bitset(global_error, 10);
}


http://infocenter.arm.com/help/index.jsp?t...qs/ka16747.html



Сообщение отредактировал Михась - Aug 24 2017, 05:59
Go to the top of the page
 
+Quote Post
alag57
сообщение Aug 24 2017, 08:35
Сообщение #36


Частый гость
**

Группа: Участник
Сообщений: 130
Регистрация: 26-06-06
Из: Березовский
Пользователь №: 18 355



Цитата(Димон Безпарольный @ Aug 23 2017, 03:11) *
1. Буду благодарен если намекнете как.

startup_stm32l476xx.s
Цитата
Stack_Size EQU 0x400;

Go to the top of the page
 
+Quote Post
x893
сообщение Aug 24 2017, 13:32
Сообщение #37


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

Группа: Свой
Сообщений: 1 333
Регистрация: 27-10-08
Из: Планета Земля
Пользователь №: 41 226



Можно включить автоматическое пошаговое выполнение и отслеживать значение SP.
Не быстро конечно, но можно отследить всё что происходит.
Можно взять Traseanalyzer или SystemView и им красивые картинки посмотреть как стэк.
Но пошаговый - это железобетонный способ.
Go to the top of the page
 
+Quote Post
Димон Безпарольн...
сообщение Aug 24 2017, 15:40
Сообщение #38


Знающий
****

Группа: Участник
Сообщений: 734
Регистрация: 29-11-10
Пользователь №: 61 247



Цитата(alag57 @ Aug 24 2017, 12:35) *
startup_stm32l476xx.s

Точно. Спасибо.
Go to the top of the page
 
+Quote Post

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

 


RSS Текстовая версия Сейчас: 21st July 2025 - 11:39
Рейтинг@Mail.ru


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