Покуда одни при каждом удобном случае мажут хабр грязью, я с большим удовольствием на нём выуживаю полезные для меня статьи, в частности:
Как защититься от переполнения стека (на Cortex M)?
Я, к сожалению, не такой лютый погромист всяких STM32 и прочих 32-х битных МК. Но таки срыв стека ловил, как раз когда переписывал предзагрузчик на одном весёлом MIPS-процессоре. Там я работал вообще на вольных хлебах, в том смысле, что весь стек инициализировался линкерным скриптом, в котором я тогда воообще не волок и брал готовый (сейчас не сильно больше волоку). В общем, суть была такова, что при вложении функции больше трёх - у меня ребутился проц. Понял я это не сразу, а путём экспериментов. В результате я тогда написал свой менеджер памяти, благо переменных было не очень много, но очень много данных и память (32 метра) была вся в моём распоряжении.
Так вот, ещё тогда я задумался, что стек - это больное и узкое место. Даже если у сильных мира сего, на которых бегает линукс, бывает срыв стека, то что бывает с маленькими процами. А что говорить про всяких ардуинщиков, которые даже об этом не думают и уверен, что у них 90% проблем - это срыв стека.
Так вот, исходя из статьи выше, я внезапно открыл для себя замечательные опции компилятора gcc -fstack-usage и... Я немного прифигел. После компиляции с этой опцией, появляется тьма файлов *.su (soviet union stack usage). Заглядываем в них, и тут я немного фигею:
Открываем функцию free_recive_buffer. Данная функция - это грязный хак-затычка, которая высасывает всё что есть в буфере uart, перед началом работы, чтобы иметь чистый буфер. Исключительно удобна при всяких опытах.
Ничего особенного, но оказывается, что переменная free_data располагается на стеке (MAX_DATA_SIZE = 1024).
Вопрос к знатокам. Я понимаю, что система у меня толстая, стек большой (кстати, а как узнать его размер в линукс?), но ведь это не есть хорошо? А если, вот я укажу там не 1024 в дефайне, а какую-нить дичь, типа 100000000? В чём преимущество размещения на стеке, в чём недостаток?
Так же, накидайте мне ещё каких-нить полезных опций компилятора gcc?
UPD Размер стека в Linux https://stackoverflow.com/questions/2275550/change-stack-size-for-a-c-application-in-linux-during-compilation-with-gnu-com
Как защититься от переполнения стека (на Cortex M)?
Я, к сожалению, не такой лютый погромист всяких STM32 и прочих 32-х битных МК. Но таки срыв стека ловил, как раз когда переписывал предзагрузчик на одном весёлом MIPS-процессоре. Там я работал вообще на вольных хлебах, в том смысле, что весь стек инициализировался линкерным скриптом, в котором я тогда воообще не волок и брал готовый (сейчас не сильно больше волоку). В общем, суть была такова, что при вложении функции больше трёх - у меня ребутился проц. Понял я это не сразу, а путём экспериментов. В результате я тогда написал свой менеджер памяти, благо переменных было не очень много, но очень много данных и память (32 метра) была вся в моём распоряжении.
Так вот, ещё тогда я задумался, что стек - это больное и узкое место. Даже если у сильных мира сего, на которых бегает линукс, бывает срыв стека, то что бывает с маленькими процами. А что говорить про всяких ардуинщиков, которые даже об этом не думают и уверен, что у них 90% проблем - это срыв стека.
Так вот, исходя из статьи выше, я внезапно открыл для себя замечательные опции компилятора gcc -fstack-usage и... Я немного прифигел. После компиляции с этой опцией, появляется тьма файлов *.su (
... reader.c:260:5:run_mode 48 static reader.c:276:5:get_data_from_reader 1088 static reader.c:293:6:free_recive_buffer 1056 static reader.c:300:10:get_raw_data 64 static ...
Открываем функцию free_recive_buffer. Данная функция - это грязный хак-затычка, которая высасывает всё что есть в буфере uart, перед началом работы, чтобы иметь чистый буфер. Исключительно удобна при всяких опытах.
void free_recive_buffer (void) {
uint8_t free_data [MAX_DATA_SIZE] = {0};
get_from_reader(free_data,MAX_DATA_SIZE,100);
}
Ничего особенного, но оказывается, что переменная free_data располагается на стеке (MAX_DATA_SIZE = 1024).
Вопрос к знатокам. Я понимаю, что система у меня толстая, стек большой (кстати, а как узнать его размер в линукс?), но ведь это не есть хорошо? А если, вот я укажу там не 1024 в дефайне, а какую-нить дичь, типа 100000000? В чём преимущество размещения на стеке, в чём недостаток?
Так же, накидайте мне ещё каких-нить полезных опций компилятора gcc?
UPD Размер стека в Linux https://stackoverflow.com/questions/2275550/change-stack-size-for-a-c-application-in-linux-during-compilation-with-gnu-com
no subject
Date: 2018-10-03 11:17 am (UTC)Сделал проверку.
В инициализации uart изменил строки:
В код функции очистки буффера закинул:
void free_recive_buffer (void) { uint8_t free_data; int counter = 0; while (get_from_reader(&free_data, 1, 100)) { counter++; }; printf("counter = %d\n", counter); }Запускаю программу, которая требует овердофига байт и дропаю её, и потом снова запускаю. Вначале стоит запуск очистки буффера, после инита юарта. И опа...
Таки откуда-то набегают байты... Так что очищать всё равно надо.
no subject
Date: 2018-10-03 03:25 pm (UTC)Вероятно это остатки ответа на первый запуск, не?
no subject
Date: 2018-10-03 03:26 pm (UTC)no subject
Date: 2018-10-03 04:35 pm (UTC)Серьезно?
Может стоит посмотреть что там пришло, а?
Может там хендшейка попытки например.
no subject
Date: 2018-10-03 04:56 pm (UTC)no subject
Date: 2018-10-03 05:02 pm (UTC)Данные в буфер могут валиться по куче причин, например контроллер полетел.
Просто читать данные и ожидать что они когда нибудь кончатся - не вариант.
Но послать конечно проще, че уж тут %)
no subject
Date: 2018-10-03 05:07 pm (UTC)Такой вариант возможен. Но маловероятен.
no subject
Date: 2018-10-03 05:15 pm (UTC)Я вроде с самого начала так и написал:
>>while (get_from_reader(&free_data, 1, 100)) {}
>Отличный способ повесить программу постоянно засирая уарт данными, либо тем что ими выглядит %)))
Ладно, может не вполне внятно, но потом же вроде нормально объяснил:
>>Объясни каким образом этот код приёмного буффера может повесить программу, а ещё что более важно, как может засрать uart?
>Наоборот.
>Код который постоянно читает данные пока они есть рискует читать их до конца жизни если с другого конца в уарт будут срать данными без перерыва.
И да, хотелось бы увидеть где и кого я обвинил в тупости?