|
перезапуск программы, непонятно почему. |
|
|
|
Jan 16 2007, 21:13
|
Участник

Группа: Новичок
Сообщений: 45
Регистрация: 30-10-06
Пользователь №: 21 801

|
есть программа, состоит из 2-х подпрограмм А и Б, выполняемых бесконечно в while (1) {} и real-time clock по timer0. 1-я выводит массив led[32] в порт D, 2-я обновляет led[32]. Проблема - два раза цикл вывода и обновления led[32] проходит нормально, в начале 3-го происходит перезапуск контроллера, замечаю по обнулению времени и led. watchdog выключен, да и время до сброса не одно, зависит от времени выполнения циклов в А и Б, и 2 сек, и 15 сек и больше, а происходит в одной и той же точке выполнения А и Б. в чем может быть дело ? как уйти от этого сброса ? p.s. попробую отследить в AVR Studio, поможет ? там вроде нет шагов назад.
Сообщение отредактировал simsim - Jan 16 2007, 21:17
|
|
|
|
|
 |
Ответов
(30 - 44)
|
Jan 18 2007, 14:35
|
Участник

Группа: Новичок
Сообщений: 19
Регистрация: 18-01-07
Пользователь №: 24 530

|
Цитата(Dog Pawlowa @ Jan 18 2007, 13:00)  Цитата(Dan_Dima @ Jan 18 2007, 13:28)  Насколько я помню подобные преобразования компилятор делает сам ( только проверил) так как преобразование идет к "большему" типу. Поэтому эти две записи эквивалентны.
Конечно сам, но на каком этапе? Отличие в записях в моменте преобразования. Преобразование происходит по ходу выполнения вычислений если говорить о том как это делаеться в обычном С. В IAR может действительно надо принудительно описывать привидение типов в том же gcc такого нет.
|
|
|
|
|
Jan 18 2007, 18:08
|
Гуру
     
Группа: Свой
Сообщений: 2 702
Регистрация: 14-07-06
Пользователь №: 18 823

|
Цитата(Dan_Dima @ Jan 18 2007, 15:35)  Преобразование происходит по ходу выполнения вычислений если говорить о том как это делаеться в обычном С. В приведенной формуле tp=(aa1*8)+bb1 компилятор IAR хранит временные результаты вычисления (aa1*8) того же типа, что и aa1 и ничего не нарушает. Переполнение происходит, так как программист не учел, что оно может произойти, а не по той причине, что IAR - это не "обычный С". Цитата(Dan_Dima @ Jan 18 2007, 15:35)  В IAR может действительно надо принудительно описывать привидение типов в том же gcc такого нет. GCC действительно по другому работает, чем IAR - сталкивался с этим. Но, подчеркиваю, разобранный пример - не свидетельство ненормальной работы IAR.
--------------------
Уходя, оставьте свет...
|
|
|
|
|
Jan 18 2007, 18:56
|

Гуру
     
Группа: Модераторы
Сообщений: 8 455
Регистрация: 15-05-06
Из: Рига, Латвия
Пользователь №: 17 095

|
Цитата(SasaVitebsk @ Jan 17 2007, 23:49)  Но я говорю немного уклончиво потому, что полностью компилятор не знает никто кроме разработчиков, а в полной мере проверить не удаётся. Для того и существуют стандарты, чтобы точно описывать "как оно должно быть","как оно не должно быть" и "а вот это хз". Последнее отдано на откуп разработчикам компиляторов. Не больше. Цитата(SasaVitebsk @ Jan 17 2007, 23:49)  Пример специально для Вас Сергей Борщ.  В библиотеках которые я выкладывал по поводу 18b20 применено динамическое распределение памяти. И там же использован массив локальный. Здесь вы путаетесь в терминах. В языке С динамическим распределением памяти называется именно работа с кучей. Локальные переменные, под которые память выделяется на стеке, в терминах С называются автоматическими. Переменные, под которые память выделяется на этапе запуска программы, называются статическими. К статическим относятся глобальные переменные и локальные переменные, объявленные с квалификатором static. В вашем примере динамического распределения я не увидел. Цитата(SasaVitebsk @ Jan 17 2007, 23:49)  Возможно Вы будете удивлены, но IAR данный массив размещает в регистрах. (Оптимизирует) Ненаказуемо  Но если вы попытаетесь взять адрес такой переменной и передать куда-либо указатель на нее, она сразу же из регистров окажется в памяти. Цитата(SasaVitebsk @ Jan 17 2007, 23:49)  2 defunct. Главное, о чём я писал в своём сообщении, что если бы компилятор произвольно использовал бы кучу, то как с ней работать? А если я её освобождаю ниже занятого уровня? Я уверен, что она не занята. Потому, что мной она не занята. Он меня ещё может контролировать. Я его - нет. я не defunct, но попытаюсь ответить: вы не можете "освободить ниже занятого уровня". Вы говорите сколько вам памяти надо, malloc выделяет в куче участок такого размера и выдает вам указатель на него. Этот участок в вашем полном распоряжении и никто на него не покусится. Когда вы хотите освободить этот участок - вы передаете free указатель на участок. Размер освобождаемого участка менеджер памяти определит сам. Повторное освобождение какого-либо участка - это ошибка в программе. Но ничего не мешает другой части программы (другой функции, задаче, другому потоку) получить из этой же кучи другой участок.
--------------------
На любой вопрос даю любой ответ"Write code that is guaranteed to work, not code that doesn’t seem to break" ( C++ FAQ)
|
|
|
|
|
Jan 18 2007, 20:15
|

Гуру
     
Группа: Свой
Сообщений: 13 372
Регистрация: 27-11-04
Из: Riga, Latvia
Пользователь №: 1 244

|
Цитата(prottoss @ Jan 18 2007, 18:40)  Единственное, в чем я был прав - массив, объявленный в функции - создается динамически!!! Нет, не "динамически" а "автоматически" - Сергей уже обьяснял!!! Цитата Так что, ребята, учитывайте это при создании приложений для АВР на ИАР  . Ни AVR, ни IAR здесь ни причем. "С", просто "С" стандартное поведение.
--------------------
Feci, quod potui, faciant meliora potentes
|
|
|
|
|
Jan 18 2007, 20:39
|

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

|
Цитата(zltigo @ Jan 19 2007, 00:15)  Цитата(prottoss @ Jan 18 2007, 18:40)  Единственное, в чем я был прав - массив, объявленный в функции - создается динамически!!!
Нет, не "динамически" а "автоматически" - Сергей уже обьяснял!!! Цитата Так что, ребята, учитывайте это при создании приложений для АВР на ИАР  . Ни AVR, ни IAR здесь ни причем. "С", просто "С" стандартное поведение. А в чем разница между "динамически" и "автоматически"??? 1. Если уж говорить по русски - я считаю что "динамически" - это на этапе исполнения кода, а Вы о чем глаголите??? 2. Про стандартное поведение Си согласен, здесь все четко
--------------------
|
|
|
|
|
Jan 18 2007, 21:15
|
    
Группа: Свой
Сообщений: 1 928
Регистрация: 11-07-06
Пользователь №: 18 731

|
Цитата(Dan_Dima @ Jan 18 2007, 14:35)  Цитата(Dog Pawlowa @ Jan 18 2007, 13:00)  Цитата(Dan_Dima @ Jan 18 2007, 13:28)  Насколько я помню подобные преобразования компилятор делает сам ( только проверил) так как преобразование идет к "большему" типу. Поэтому эти две записи эквивалентны.
Конечно сам, но на каком этапе? Отличие в записях в моменте преобразования. Преобразование происходит по ходу выполнения вычислений если говорить о том как это делаеться в обычном С. В IAR может действительно надо принудительно описывать привидение типов в том же gcc такого нет. По стандарту все операнды с разрядностью, меньшей int, в целочисленных выражениях обрабатываются как int, и к разрядности lvalue приводится только результат. Обработка операндов с меньшей разрядностью без приведения к int - интимное дело оптимизатора. Для проверки можете посмотреть асм листинг без оптимизации. Цитата(prottoss @ Jan 18 2007, 19:40)  defunct был прав - массив, объявленный в функции, создается не в куче, а в стеке данных (я говрю про ИАР). Проверил листинг ассемблера - все так и есть. И как следствие - задание соответствующего размера стека. Цитата Единственное, в чем я был прав - массив, объявленный в функции - создается динамически!!! Как уже заметил Сергей Борщ, такие переменные называются автоматическими, и в полном соответствии со стандартом языка создаются при входе в функцию и уничтожаются при выходе из нее. По умолчанию размещаются на стеке, но при включенном оптимизаторе легко могут оказаться в регистрах. PS: извините за невольный частичный повтор - писАлось больше часа, задергали звонками и неотложными проблемами.
|
|
|
|
|
Jan 18 2007, 21:44
|
    
Группа: Свой
Сообщений: 1 928
Регистрация: 11-07-06
Пользователь №: 18 731

|
Цитата(prottoss @ Jan 18 2007, 20:39)  Цитата(zltigo @ Jan 19 2007, 00:15)  Цитата(prottoss @ Jan 18 2007, 18:40)  Единственное, в чем я был прав - массив, объявленный в функции - создается динамически!!!
Нет, не "динамически" а "автоматически" - Сергей уже обьяснял!!! Цитата Так что, ребята, учитывайте это при создании приложений для АВР на ИАР  . Ни AVR, ни IAR здесь ни причем. "С", просто "С" стандартное поведение. А в чем разница между "динамически" и "автоматически"??? Автоматическая переменная будет удалена автоматически при выходе из функции, в которой она была определена. Удаление динамических переменных по мере их ненадобности - задача программера. Распространненость подобных ошибок (неосвобождение памяти) приводилась как аргумент за корявость всего языка.
|
|
|
|
|
Jan 18 2007, 21:59
|
    
Группа: Свой
Сообщений: 1 928
Регистрация: 11-07-06
Пользователь №: 18 731

|
Цитата(prottoss @ Jan 18 2007, 21:43)  Канешна, это все здорово очень, объясните тада, умные сотоварищи, зачем мне указывать размер стека данных, еслиФ все равно компилятор и иже с ними, создаст массив в этом самом стекеданных, то бишь нарушит мое НЕОСПОРИМОЕ правило??? Не понял про "мое НЕОСПОРИМОЕ правило". Вы же можете среднепотолочно прикинуть требуемый размер стека с учетом вложенности подпрограмм (и их потребностей для локальных переменных) и прерываний. А у компилятора по стеку правило одно: сказали "Отсель", значит так и будет. Цитата(prottoss @ Jan 18 2007, 21:52)  Цитата(xemul @ Jan 19 2007, 01:44)  Автоматическая переменная будет удалена автоматически при выходе из функции, в которой она была определена. А что, она будет создана не динамически? Вы просили объяснить разницу между автоматическими и динамическими объектами в терминологии С. А в жизни вообще все относительно - статические объекты с точки зрения программы существуют всегда, а с точки зрения ОС - только пока живет программа. Считать их динамическими?
|
|
|
|
|
Jan 18 2007, 22:04
|

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

|
Цитата(xemul @ Jan 19 2007, 01:59)  Цитата(prottoss @ Jan 18 2007, 21:43)  Канешна, это все здорово очень, объясните тада, умные сотоварищи, зачем мне указывать размер стека данных, еслиФ все равно компилятор и иже с ними, создаст массив в этом самом стекеданных, то бишь нарушит мое НЕОСПОРИМОЕ правило???
Не понял про "мое НЕОСПОРИМОЕ правило". Вы же можете среднепотолочно прикинуть требуемый размер стека с учетом вложенности подпрограмм (и их потребностей для локальных переменных) и прерываний. А у компилятора по стеку правило одно: сказали "Отсель", значит так и будет. Угу, а тада зафига мне куча в Си??? Без плюсиков... Цитата(xemul @ Jan 19 2007, 01:59)  Вы же можете среднепотолочно прикинуть требуемый размер стека Гон всезнайки????????????????????????
--------------------
|
|
|
|
|
Jan 19 2007, 00:20
|
    
Группа: Свой
Сообщений: 1 928
Регистрация: 11-07-06
Пользователь №: 18 731

|
Цитата(prottoss @ Jan 18 2007, 22:04)  Цитата(xemul @ Jan 19 2007, 01:59)  Цитата(prottoss @ Jan 18 2007, 21:43)  Канешна, это все здорово очень, объясните тада, умные сотоварищи, зачем мне указывать размер стека данных, еслиФ все равно компилятор и иже с ними, создаст массив в этом самом стекеданных, то бишь нарушит мое НЕОСПОРИМОЕ правило???
Не понял про "мое НЕОСПОРИМОЕ правило". Вы же можете среднепотолочно прикинуть требуемый размер стека с учетом вложенности подпрограмм (и их потребностей для локальных переменных) и прерываний. А у компилятора по стеку правило одно: сказали "Отсель", значит так и будет. Угу, а тада зафига мне куча в Си??? Без плюсиков... Повторюсь за всех, уже говоривших об этом: куча используется для динамического выделения памяти, автоматические переменные обычно размещаются на стеке. Цитата Цитата(xemul @ Jan 19 2007, 01:59)  Вы же можете среднепотолочно прикинуть требуемый размер стека Гон всезнайки???????????????????????? Вам не доводилось этим заниматься и установки стека по умолчанию достаточно? Ну и слава богу и разработчикам используемых Вами компиляторов. Если помните, причина возникновения этого треда крылась в некорректной работе со стеком. Подобные треды возникают достаточно регулярно, и в них неоднократно обсуждались способы контроля переполнения и оценки требуемой глубины стека. Кста, Вы в них активно участвовали. Не отложилось? И, плз, если Вы чего-то не знаете, не выставляйте это напоказ несколько агрессивным образом.
|
|
|
|
|
Jan 19 2007, 01:32
|

кекс
     
Группа: Свой
Сообщений: 3 825
Регистрация: 17-12-05
Из: Киев
Пользователь №: 12 326

|
Цитата(Сергей Борщ @ Jan 18 2007, 18:56)  ... Respect! Сомневаюсь, что у меня получилось бы лучше раскрыть вопрос. Цитата(SasaVitebsk @ Jan 17 2007, 23:49)  2 defunct. Главное, о чём я писал в своём сообщении, что если бы компилятор произвольно использовал бы кучу, то как с ней работать? А если я её освобождаю ниже занятого уровня? Я уверен, что она не занята. Потому, что мной она не занята. Он меня ещё может контролировать. Я его - нет. Компилятор с кучей не работает вовсе. "Куча" - это просто куча - доступная в run-time память. Для того чтобы с ней работать нужен также run-time менеджер памяти. Попробую продемонстрировать динамическое распределение памяти на простейшем примере. Допустим нам надо выделять массивы объемом 64 байта (например для хранения подготовленного к отправке пакета данных того же modbus), сколько их потребуется - неизвестно, каким будет их время жизни тоже низвестно. Представьте, что у Вас есть статический массив MyHeap, элементами которого являются некоторые структуры, например такие: Код typedef U8 PSTORAGE[64]; typedef U8 *PTR;
typedef struct __tagHeapPart { U8 Busy; PSTORAGE storage; } THEAP_PART, *PHEAP_PART;
THEAP_PART MyHeap[ 16 ]; #define COUNT( somearray ) (sizeof(somearray) / sizeof(somearray[0])) пишем фукции динамического выделения и освобождения блока памяти: Код PTR my_alloc_part(void) { U8 i; PTR retval = NULL; for (i = 0; i < COUNT(MyHeap); i++) { if (!MyHeap[i].Busy) // блок не занят { MyHeap[i].Busy = TRUE; // занимаем его retval = MyHeap[i].storage; break; } } return retval; }
void my_free_part(PSTORAGE pPart) { if (pPart) { pPart[-1] = 0; // освобождаем блок (Busy = false) } } Т.о. с помощью my_alloc_part вам будет выделен кусочек статического массива, который Вы смело можете использовать столько сколько нужно. Когда этот кусочек будет ненужен - достаточно вызвать my_free_part и он опять вернется в "кучу".
|
|
|
|
|
Jan 19 2007, 02:21
|
Гуру
     
Группа: Свой
Сообщений: 2 712
Регистрация: 28-11-05
Из: Беларусь, Витебск, Строителей 18-4-220
Пользователь №: 11 521

|
Цитата(Сергей Борщ @ Jan 18 2007, 19:56)  Цитата(SasaVitebsk @ Jan 17 2007, 23:49)  Но я говорю немного уклончиво потому, что полностью компилятор не знает никто кроме разработчиков, а в полной мере проверить не удаётся.
Для того и существуют стандарты, чтобы точно описывать "как оно должно быть","как оно не должно быть" и "а вот это хз". Последнее отдано на откуп разработчикам компиляторов. Не больше. Цитата(SasaVitebsk @ Jan 17 2007, 23:49)  Пример специально для Вас Сергей Борщ.  В библиотеках которые я выкладывал по поводу 18b20 применено динамическое распределение памяти. И там же использован массив локальный. Здесь вы путаетесь в терминах. В языке С динамическим распределением памяти называется именно работа с кучей. Локальные переменные, под которые память выделяется на стеке, в терминах С называются автоматическими. Переменные, под которые память выделяется на этапе запуска программы, называются статическими. К статическим относятся глобальные переменные и локальные переменные, объявленные с квалификатором static. В вашем примере динамического распределения я не увидел. Цитата(SasaVitebsk @ Jan 17 2007, 23:49)  Возможно Вы будете удивлены, но IAR данный массив размещает в регистрах. (Оптимизирует) Ненаказуемо  Но если вы попытаетесь взять адрес такой переменной и передать куда-либо указатель на нее, она сразу же из регистров окажется в памяти. Цитата(SasaVitebsk @ Jan 17 2007, 23:49)  2 defunct. Главное, о чём я писал в своём сообщении, что если бы компилятор произвольно использовал бы кучу, то как с ней работать? А если я её освобождаю ниже занятого уровня? Я уверен, что она не занята. Потому, что мной она не занята. Он меня ещё может контролировать. Я его - нет. я не defunct, но попытаюсь ответить: вы не можете "освободить ниже занятого уровня". Вы говорите сколько вам памяти надо, malloc выделяет в куче участок такого размера и выдает вам указатель на него. Этот участок в вашем полном распоряжении и никто на него не покусится. Когда вы хотите освободить этот участок - вы передаете free указатель на участок. Размер освобождаемого участка менеджер памяти определит сам. Повторное освобождение какого-либо участка - это ошибка в программе. Но ничего не мешает другой части программы (другой функции, задаче, другому потоку) получить из этой же кучи другой участок. Я не путаюсь в терминах. Я пишу "В библиотеках которые я выкладывал по поводу 18b20 применено динамическое выделение памяти. И там же использован массив локальный." и это так и есть! Просто п/п пример, которой я привёл не использует динамического выделения, а использует локальный массив. Динамическое выделение исп. в другом месте этой же библиотеки. Код uint8_t OW_cnt_device(void) { uint8_t Cnt_Device; // Число устройств на шине
Cnt_Device=0; if(!OW_reset()) // Начинается когда импульс присутствия обнаружен { lastDiscrep = 0; // восстановите последнее несоответствие rom поиска глобальное OW_Rom_Device=CurrentAddr=malloc(8); // Зарезервировать память под ROM while (Next()) // Продолжить пока все дополнительные устройства не будут обнаружены { Cnt_Device++; } } return(Cnt_Device); }
void OW_free(void) // Освободить память занятую под датчики { free(OW_Rom_Device); // Освободить память } Я определяю колличество 1-wire устройств на шине (Cnt_Device) и их адреса в объёме Cnt_Device*7+1 сохраняю в куче. Это было выложено в библиотеках для всеобщего 18.10.2006, что явно раньше этой дискусии. А примером по локальному массиву, я возразил что он не всегда ложится на стэк. В моём случае компилятор при оптимизации разместил его в регистрах. По поводу высказывания. Цитата я не defunct, но попытаюсь ответить: вы не можете "освободить ниже занятого уровня". Вы говорите сколько вам памяти надо, malloc выделяет в куче участок такого размера и выдает вам указатель на него. Этот участок в вашем полном распоряжении и никто на него не покусится. Когда вы хотите освободить этот участок - вы передаете free указатель на участок. Размер освобождаемого участка менеджер памяти определит сам. Повторное освобождение какого-либо участка - это ошибка в программе. Но ничего не мешает другой части программы (другой функции, задаче, другому потоку) получить из этой же кучи другой участок. Вы меня не поняли. Я имел в виду следующее. Представьте что я выполнил процедуру определения датчиков OW_cnt_device() и получил указатель на свободное место в куче. После этого компилятор без моего ведома разместил там ещё какое-то колличество переменных. Не зная об этом я беру и выполняю операцию OW_free(). В результате происходит крах проги. Поэтому я и высказал сомнение о реальности. Я редко высказываюсь категорично. Приведу пример. В серьёзных (во всяком случае я об этом читал) системах/компиляторах (В винде этого нет) существуют так называемые "сборщики мусора". Которые убирают дыры образующиеся в куче при выполнении операций new/free. Таким образом менеджер памяти там очень мощный. Он может перераспределять данные, в том числе от разных пользователей/потоков. Здесь менеджер - один указатель и пара сравнений. Написано пользователь сам должен. Оно и понятно "обеднённая" система.
|
|
|
|
|
  |
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|