|
перезапуск программы, непонятно почему. |
|
|
|
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
|
|
|
|
|
 |
Ответов
(1 - 60)
|
Jan 16 2007, 21:43
|
Участник

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

|
Цитата(bodja74 @ Jan 16 2007, 21:33)  SREG и регистры сохраняются в прерывании ? Прога на СИ. специально не забочусь о них.
|
|
|
|
|
Jan 17 2007, 13:04
|
Местный
  
Группа: Участник
Сообщений: 416
Регистрация: 18-04-06
Из: Челябинск
Пользователь №: 16 219

|
Цитата(simsim @ Jan 16 2007, 21:13)  есть программа, состоит из 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, поможет ? там вроде нет шагов назад. Код в Студию!!!
|
|
|
|
|
Jan 17 2007, 13:41
|

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

|
Цитата(simsim @ Jan 17 2007, 01:13)  есть программа, состоит из 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, поможет ? там вроде нет шагов назад. Возможно, из за переполнения стека данных, реомендую увеличить в два раза. Если пользуетесь ИАРом, то по умолчанию глубина стека данных равна 0x20 (или 32 - ИМХО для того, чтобы можно было, при входе впрерывание, сохранить все 32 регистра). Если какая то процедура в программе, кроме прерывания пользуется стеком данных, естественно, он переполнится, и корабль потонет Поменять значение можно в Главное меню->Project->Options->General Options->System->Data Stack (RSTACK)
--------------------
|
|
|
|
|
Jan 17 2007, 17:46
|
Участник

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

|
Цитата(GDI @ Jan 17 2007, 12:42)  Индексы массивов не выходят ли за границы оных, стек не переполняется? Какой компилятор? Да может и исходник бы здесь тоже не помешал.. Компилятор CodeVisionAVR 1.24.8, индексы в порядке, потому что два раза проходит нормально, а на третий выполняя то же самое перезапускается. Размер стека 256 байт, неужели мало? Что такое HEAP SIZE в настройках CVAVR ?
|
|
|
|
|
Jan 17 2007, 18:02
|

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

|
Цитата(simsim @ Jan 17 2007, 21:46)  Цитата(GDI @ Jan 17 2007, 12:42)  Индексы массивов не выходят ли за границы оных, стек не переполняется? Какой компилятор? Да может и исходник бы здесь тоже не помешал..
Компилятор CodeVisionAVR 1.24.8, индексы в порядке, потому что два раза проходит нормально, а на третий выполняя то же самое перезапускается. Размер стека 256 байт, неужели мало? Что такое HEAP SIZE в настройках CVAVR ? Я не пользовал CodeVisionAVR, но для ИАРа есть два стека - первый стек данных, второй - стек программ. Первый нужен для сохранения переменных, расположенных в регистрах, второй служит для выхода из подпрограмм. HEAP SIZE - скорее всего, размер кучи в глобальной памяти данных SRAM. Куча - это память, доступная для программы. Используется для динамически создаваемых переменных, под которые компилятор не может выделить регистр. Допустим Вы объявили массив, как глобальную переменную - он будет создан не в куче, а на этапе запуска стартап-кода. Если же массив будет объявлен внутри функции, то, возможно, он будет создаваться динамически, во время выполнения функции, как раз в этой самой куче.
--------------------
|
|
|
|
|
Jan 17 2007, 19:00
|
Участник

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

|
Цитата(simsim @ Jan 17 2007, 17:46)  Цитата(GDI @ Jan 17 2007, 12:42)  Индексы массивов не выходят ли за границы оных, стек не переполняется? Какой компилятор? Да может и исходник бы здесь тоже не помешал..
Компилятор CodeVisionAVR 1.24.8, индексы в порядке, потому что два раза проходит нормально, а на третий выполняя то же самое перезапускается. Размер стека 256 байт, неужели мало? Что такое HEAP SIZE в настройках CVAVR ? Увеличил стек до 500. Теперь перезапускается после 5-го обновления массива leds, а не 3-го как раньше. В подпрограмме обновления leds есть обращение к ассемблерной подпрограмме - #pragma warn- // this will prevent warnings unsigned char asm_font(unsigned char aa1, unsigned char bb1) { #asm .def temp =r16 .def zh =r31 .def zl =r30 .def ak =r23 .def bk =r24 .def yh =r29 .def yl =r28 .................. lpm r30,z ; результат ret #endasm } #pragma warn+ // enable warnings Может здесь причина?
|
|
|
|
|
Jan 17 2007, 19:10
|
Гуру
     
Группа: Свой
Сообщений: 2 712
Регистрация: 28-11-05
Из: Беларусь, Витебск, Строителей 18-4-220
Пользователь №: 11 521

|
Цитата(prottoss @ Jan 17 2007, 19:02)  Допустим Вы объявили массив, как глобальную переменную - он будет создан не в куче, а на этапе запуска стартап-кода.
Если же массив будет объявлен внутри функции, то, возможно, он будет создаваться динамически, во время выполнения функции, как раз в этой самой куче. Для IAR даже если массив объявлен внутри ф-ции, то он всё равно будет создан "на этапе запуска стартап-кода". Даже если он и будет создан динамически (не программистом а компилятором), то он будет создан за счёт памяти выделенной под это на этапе линковки. А куча полностью предоставлена программисту. (Как в С++ не знаю). Я могу выделить память и освободить её. М/у моими действиями ничего происходить с кучей не должно. Ничего без моего участия. Таким образом учитывая, что парень не слышал о таком слове  - куча не занята, и она явно к этому не имеет никакого отношения.
|
|
|
|
|
Jan 17 2007, 19:25
|

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

|
Цитата(SasaVitebsk @ Jan 17 2007, 23:10)  Цитата(prottoss @ Jan 17 2007, 19:02)  Допустим Вы объявили массив, как глобальную переменную - он будет создан не в куче, а на этапе запуска стартап-кода.
Если же массив будет объявлен внутри функции, то, возможно, он будет создаваться динамически, во время выполнения функции, как раз в этой самой куче.
Для IAR даже если массив объявлен внутри ф-ции, то он всё равно будет создан "на этапе запуска стартап-кода". А я Вам говорю, что в куче, давайте поспорим  Ваши аргументы какие?
--------------------
|
|
|
|
|
Jan 17 2007, 19:32
|
Профессионал
    
Группа: Свой
Сообщений: 1 235
Регистрация: 14-05-05
Из: Санкт-Петербург
Пользователь №: 5 008

|
Цитата индексы в порядке, потому что два раза проходит нормально это ничего не значит... Цитата Теперь перезапускается после 5-го обновления массива leds ...и это тому подтверждение Цитата #pragma warn- // this will prevent warnings unsigned char asm_font(unsigned char aa1, unsigned char bb1) { #asm .def temp =r16 .def zh =r31 .def zl =r30 .def ak =r23 .def bk =r24 .def yh =r29 .def yl =r28 .................. lpm r30,z ; результат ret #endasm } #pragma warn+ // enable warnings Что то я не вижу сохранение в стеке используемых регистров и, соответственно, последующего их восстановления, вполне может быть, что проблема в этом. А что показала проверка в AVR Studio?
--------------------
|
|
|
|
|
Jan 17 2007, 19:35
|
Участник

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

|
Для IAR даже если массив объявлен внутри ф-ции, то он всё равно будет создан "на этапе запуска стартап-кода". [/quote] А я Вам говорю, что в куче, давайте поспорим  Ваши аргументы какие? [/quote] Куча в нуле. Пробовал делать ее 100 - безрезультатно. Похоже что стек выбивает. AVR написала что "AVR Simulator: Stack pointer changed after subroutine call", не заметил после какой, долго идет симуляция, похоже после asm_font()
|
|
|
|
|
Jan 17 2007, 19:36
|
Гуру
     
Группа: Свой
Сообщений: 2 712
Регистрация: 28-11-05
Из: Беларусь, Витебск, Строителей 18-4-220
Пользователь №: 11 521

|
Цитата(simsim @ Jan 17 2007, 20:00)  Цитата(simsim @ Jan 17 2007, 17:46)  Цитата(GDI @ Jan 17 2007, 12:42)  Индексы массивов не выходят ли за границы оных, стек не переполняется? Какой компилятор? Да может и исходник бы здесь тоже не помешал..
Компилятор CodeVisionAVR 1.24.8, индексы в порядке, потому что два раза проходит нормально, а на третий выполняя то же самое перезапускается. Размер стека 256 байт, неужели мало? Что такое HEAP SIZE в настройках CVAVR ? Увеличил стек до 500. Теперь перезапускается после 5-го обновления массива leds, а не 3-го как раньше. В подпрограмме обновления leds есть обращение к ассемблерной подпрограмме - #pragma warn- // this will prevent warnings unsigned char asm_font(unsigned char aa1, unsigned char bb1) { #asm .def temp =r16 .def zh =r31 .def zl =r30 .def ak =r23 .def bk =r24 .def yh =r29 .def yl =r28 .................. lpm r30,z ; результат ret #endasm } #pragma warn+ // enable warnings Может здесь причина? Если у Вас зависит от числа вызывов, то это однозначно указывает, что у Вас плывёт указатель стэка. Одного или другого. Зачем Вы замыливаете причину??? Просто найдите и устраните! Как собирались. Верните всё как было (всё таки два цикла меньше чем 5 гнать) и прогоните в Studio. Обратите внимание на указатель стэка в одном и том же месте. Теперь вопрос 2. Зачем Вы путаете Си и Asm если Вы ещё в самом начале пути??? Вы уверены что регистры которые Вы портите в Asm не использует компилятор??? Простите, но для меня Ваша прога, просто лишена смысла. Как можно результат занести в регистр? И что? А если при следующей компиляции компилятор поменяет использование регистров??? Это же его право! Я понимаю ещё если бы Вы с переменной работали, а используемые регистры сохраняли. И то! Зачем Вам вообще это. Используйте чистый Си. Я уверен, - то что Вы хотите сделать на Asm можно реализовать и в рамках языка! Просто спросите в форуме - как это сделать. Приведу пример. В начале своего последнего проекта, я хотел делать ассемблерные п/п. Чтобы ускорить работу в некоторых местах. Но решил сделать это после отладки проекта. А, сначала, всё реализовать на Си. Теперь проект закончен. И, наверное я уже просто не буду этим заниматься. У меня просто банально всё работает. Производительность отличная. Так зачем этот цирк?
|
|
|
|
|
Jan 17 2007, 20:14
|

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

|
Чтобы все не спорили. Массивы, объявленные внутри функции(локальные), равно как и локальные переменные, и в С и в С++ размещаются на стеке. В ИАРе на стеке данных (CSTACK). В куче в С++ размещаются объекты созданные через вызов operator new. В "голом" С в куче "само" не размещается ничего. Программист может зарезервировать себе кусочек памяти в куче библиотечными функциями malloc, calloc и в этот кусочек разместить что захочет. Иначе никак. Цитата(SasaVitebsk @ Jan 17 2007, 18:36)  Как можно результат занести в регистр? И что? А если при следующей компиляции компилятор поменяет использование регистров??? Это же его право! В защиту автора функции: В данном случае речь идет о CV, а он использует именно R30:R31 для передачи параметров и возврата значений. Это описано в его доке и просто так не поменяется. Цитата(SasaVitebsk @ Jan 17 2007, 18:36)  Приведу пример. В начале своего последнего проекта, я хотел делать ассемблерные п/п. Чтобы ускорить работу в некоторых местах. Но решил сделать это после отладки проекта. А, сначала, всё реализовать на Си. Теперь проект закончен. И, наверное я уже просто не буду этим заниматься. У меня просто банально всё работает. Производительность отличная. Так зачем этот цирк? Вот тут полностью согласен. Но если автор настаивает, то можно порекомендовать вместо этой функции вставить затычку, типа такой: Код unsigned char pass; unsigned char asm_font(unsigned char aa1, unsigned char bb1) { return ++pass; } и посмотреть как будет работать. Если вешаться перестанет, то написать простую программу: Код void main() { for(;;) asm_font(1,2); } и прогнать ее в avrstudio, обращая внимание на стек, на изменяющуюся память, на регистры. А можно и сюда текст функции выложить - коллективом ошибки ловятся быстрее.
--------------------
На любой вопрос даю любой ответ"Write code that is guaranteed to work, not code that doesn’t seem to break" ( C++ FAQ)
|
|
|
|
|
Jan 17 2007, 20:37
|
Местный
  
Группа: Свой
Сообщений: 408
Регистрация: 21-10-06
Из: Санкт-Петербург
Пользователь №: 21 527

|
Цитата(AndryG @ Jan 17 2007, 20:21)  Не вчитывался в посты народа ... звыняйте .. в АСМ-вставке Вы используете R30 - в CVAVR - это самый главный регистр - указатель стека!!! Вот с ним Вы беду и делаете. Если Ваша вставка - функция - подавно все развалится - прочтите раздел хелпа по функциям асемблерным - там указано что и как сохранять на примере кода. Цитата из хелпа CV - "The registers R0, R1, R22, R23, R24, R25, R26, R27, R30 and R31 can be freely used in assembly routines." R30,R31 используются для возврата результата функции. Указатель стека - R28,R29.
|
|
|
|
|
Jan 17 2007, 21:06
|
Участник

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

|
Заменил ассемблерную функцию на СИ-шную unsigned char asm_font(unsigned char aa1, unsigned char bb1) { unsigned int tp; tp=(aa1*8)+bb1; return font8[tp]; } но теперь другая проблема- при отладке в AVR Studio аа1=207, tp получается равным 121 !!! не поддается осмыслению ... p.s. ОТ перезапуска избавился.спасибо.
Сообщение отредактировал simsim - Jan 17 2007, 21:08
|
|
|
|
|
Jan 17 2007, 21:35
|
Участник

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

|
Цитата(simsim @ Jan 17 2007, 21:06)  Заменил ассемблерную функцию на СИ-шную unsigned char asm_font(unsigned char aa1, unsigned char bb1) { unsigned int tp; tp=(aa1*8)+bb1; return font8[tp]; } но теперь другая проблема- при отладке в AVR Studio аа1=207, tp получается равным 121 !!! не поддается осмыслению ... p.s. ОТ перезапуска избавился.спасибо. Спасибо, нашел - tp=aa1; tp*=8; tp+=bb1; (СИ это вам не математика :-)
|
|
|
|
|
Jan 18 2007, 00:49
|
Гуру
     
Группа: Свой
Сообщений: 2 712
Регистрация: 28-11-05
Из: Беларусь, Витебск, Строителей 18-4-220
Пользователь №: 11 521

|
Цитата(SasaVitebsk @ Jan 17 2007, 20:10)  Для IAR даже если массив объявлен внутри ф-ции, то он всё равно будет создан "на этапе запуска стартап-кода". Даже если он и будет создан динамически (не программистом а компилятором), то он будет создан за счёт памяти выделенной под это на этапе линковки. А куча полностью предоставлена программисту. (Как в С++ не знаю). Я могу выделить память и освободить её. М/у моими действиями ничего происходить с кучей не должно. Ничего без моего участия. Таким образом учитывая, что парень не слышал о таком слове  - куча не занята, и она явно к этому не имеет никакого отношения. 2 defunct поясни пожалуйста, что я сказал неправильно. Я не для спора, а для своего понимания. Смею предположить, что неверна лишь выдержка из поста Prottoss "на этапе запуска стартап-кода". Но я её просто как выдержку привёл, а имелл ввиду что сама прога полностью сгенерирована к моменту запуска. И место под переменные уже выделены. Это так не только в Си. С динамической памятью работать приходилось. Посмотри пожалуйста следующую за вырванной фразу. Я пишу, "Даже если он и будет создан динамически (не программистом а компилятором), то он будет создан за счёт памяти выделенной под это на этапе линковки." То есть я как раз и описываю этот вариант. В моём сообщении не это главное. Опишу чуть ниже. 2 Сергей Борщ по поводу первого раздела, именно это я и хотел сказать но у меня не получилось.  Но я говорю немного уклончиво потому, что полностью компилятор не знает никто кроме разработчиков, а в полной мере проверить не удаётся. А в документах, можно кое что упустить. Пример специально для Вас Сергей Борщ.  В библиотеках которые я выкладывал по поводу 18b20 применено динамическое распределение памяти. И там же использован массив локальный. приведу текст для понимания. Код //Чтение температуры int8_t read_scratchpad(uint8_t tip) { uint8_t scratchpad[8]; uint8_t crc = 0;
OW_write_byte(READ_SCRATCHPAD); // читаем scratchpad 0xBE for (uint8_t c1 = 0; c1 < 8; c1++) { scratchpad[c1] = OW_read_byte(); // Принять данные с 1 Wire шины crc = OW_crc8(crc, scratchpad[c1]); // Посчитать CRC8 для 1 Wire шины } crc=OW_crc8(crc, OW_read_byte()); OW_reset(); if (crc == 0) // Проверить CRC8 для 1 Wire шины { if(tip==DS18B20TIP) return ((scratchpad[1] << 4) | ((scratchpad[0]+8) >> 4)); else return ((scratchpad[1] & 0x80) | ((scratchpad[0]+1) >> 1)); } else return ( ERROR_CRC); // Message -80 } Возможно Вы будете удивлены, но IAR данный массив размещает в регистрах. (Оптимизирует) 2 defunct. Главное, о чём я писал в своём сообщении, что если бы компилятор произвольно использовал бы кучу, то как с ней работать? А если я её освобождаю ниже занятого уровня? Я уверен, что она не занята. Потому, что мной она не занята. Он меня ещё может контролировать. Я его - нет. Поэтому я и высказал сомнение. Этого нет даже на PC.
|
|
|
|
|
Jan 18 2007, 03:43
|
Участник

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

|
Всем привет. Я можнт что-то не понимаю скажите а разве между этими строками есть разница. tp=(aa1*8)+bb1; и tp=aa1; tp*=8; tp+=bb1;
|
|
|
|
|
Jan 18 2007, 08:27
|

developer
   
Группа: Свой
Сообщений: 902
Регистрация: 12-04-06
Из: Казань
Пользователь №: 16 032

|
Цитата(Dan_Dima @ Jan 18 2007, 03:43)  Всем привет. Я можнт что-то не понимаю скажите а разве между этими строками есть разница. tp=(aa1*8)+bb1; и tp=aa1; tp*=8; tp+=bb1; aa1 объявлена как char и при умножении aa1*8 вероятно происходит переполнение, а tp объявлена как int и при tp=aa1; tp*=8; так как tp это int переполнения не происходит. Сделай простую проверку, объяви aa1 как int и посмотри результат своего первого выражения tp = (aa1*8) + bb1;
--------------------
Все может быть и быть все может, и лишь того не может быть-чего уж точно быть не может, хотя..и это может быть.
|
|
|
|
|
Jan 18 2007, 09:19
|
Участник

Группа: Участник
Сообщений: 51
Регистрация: 8-01-07
Из: Одесса
Пользователь №: 24 196

|
Цитата(Dan_Dima @ Jan 18 2007, 02:43)  Всем привет. Я можнт что-то не понимаю скажите а разве между этими строками есть разница. tp=(aa1*8)+bb1; и tp=aa1; tp*=8; tp+=bb1; tp=(int)aa1*8+bb1;
--------------------
Опыт - это та чудесная штука, которая позволяет вам узнать ошибку, когда вы ее повторите.
|
|
|
|
|
Jan 18 2007, 12:28
|
Участник

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

|
Цитата(dimka76 @ Jan 18 2007, 08:27)  Цитата(Dan_Dima @ Jan 18 2007, 03:43)  Всем привет. Я можнт что-то не понимаю скажите а разве между этими строками есть разница. tp=(aa1*8)+bb1; и tp=aa1; tp*=8; tp+=bb1;
aa1 объявлена как char и при умножении aa1*8 вероятно происходит переполнение, а tp объявлена как int и при tp=aa1; tp*=8; так как tp это int переполнения не происходит. Сделай простую проверку, объяви aa1 как int и посмотри результат своего первого выражения tp = (aa1*8) + bb1; Насколько я помню подобные преобразования компилятор делает сам ( только проверил) так как преобразование идет к "большему" типу. Поэтому эти две записи эквивалентны.
|
|
|
|
|
Jan 18 2007, 13:25
|
Участник

Группа: Участник
Сообщений: 51
Регистрация: 8-01-07
Из: Одесса
Пользователь №: 24 196

|
Насколько я помню подобные преобразования компилятор делает сам ( только проверил) так как преобразование идет к "большему" типу. Поэтому эти две записи эквивалентны. [/quote]
IAR компилятору все равно к какому типу вы приравниваете. Если в выражении берут участие 8-ми битные данные, то будет применена 8-ми битная арифметика. Для оптимизации программы. А за переполнением следите сами.
--------------------
Опыт - это та чудесная штука, которая позволяет вам узнать ошибку, когда вы ее повторите.
|
|
|
|
|
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. Таким образом менеджер памяти там очень мощный. Он может перераспределять данные, в том числе от разных пользователей/потоков. Здесь менеджер - один указатель и пара сравнений. Написано пользователь сам должен. Оно и понятно "обеднённая" система.
|
|
|
|
|
Jan 19 2007, 11:11
|

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

|
Цитата(xemul @ Jan 19 2007, 04:20)  Цитата(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, 12:06
|

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

|
Цитата(SasaVitebsk @ Jan 19 2007, 01:21)  Я не путаюсь в терминах. Я пишу "В библиотеках которые я выкладывал по поводу 18b20 применено динамическое выделение памяти. Да, после приведенного кода снимаю все возражения и обвинения  Извиняюсь, не смотрел ваши библиотеки, ограничился лишь анализом приведенного куска. Подумал, что раз уж вы выложили кусочек кода, то решили облегчить мне задачу поиска исходников этих библиотек и в представленном коде есть все, что необходимо для обсуждения. Цитата(SasaVitebsk @ Jan 19 2007, 01:21)  Это было выложено в библиотеках для всеобщего 18.10.2006, что явно раньше этой дискусии. Бывает, что некоторые темы я пропускаю Цитата(SasaVitebsk @ Jan 19 2007, 01:21)  А примером по локальному массиву, я возразил что он не всегда ложится на стэк. В моём случае компилятор при оптимизации разместил его в регистрах. Это да, с этим я не спорю. Я пытался спорить с чьим-то утверждением, что компилятор может разместить его в куче. Цитата(SasaVitebsk @ Jan 19 2007, 01:21)  Вы меня не поняли. Я имел в виду следующее. Представьте что я выполнил процедуру определения датчиков OW_cnt_device() и получил указатель на свободное место в куче. После этого компилятор без моего ведома разместил там ещё какое-то колличество переменных. Где там? В куче? Зарадибога. Заметьте, вы получили указатель не "на свободное место в куче", а на свободный участок указанного вами размера. В этот участок никто больше не залезет. Но и вы не имеете права лезть за границы этого участка. Цитата(SasaVitebsk @ Jan 19 2007, 01:21)  Не зная об этом я беру и выполняю операцию OW_free(). В результате происходит крах проги. Поэтому я и высказал сомнение о реальности. Никакого краха. В кучу возвращается выделенный вам участок, на который указывал OW_Rom_Device. Остальные участки если и были выделены кому-то без вашего ведома продолжают существовать. Цитата(SasaVitebsk @ Jan 19 2007, 01:21)  Я редко высказываюсь категорично. Приведу пример. В серьёзных (во всяком случае я об этом читал) системах/компиляторах (В винде этого нет) существуют так называемые "сборщики мусора". Тут я тоже не буду утверждать категорично - изучал вопрос довольно поверхностно и для аргументированной беседы мне нужно обратиться к литературе, а литература в данный момент не доступна (она на работе, я-дома). Если есть желание - можем продолжить в понедельник, можно в отдельной ветке.
--------------------
На любой вопрос даю любой ответ"Write code that is guaranteed to work, not code that doesn’t seem to break" ( C++ FAQ)
|
|
|
|
|
Jan 19 2007, 12:21
|

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

|
Цитата(prottoss @ Jan 18 2007, 19:39)  А в чем разница между "динамически" и "автоматически"??? "динамически" == "в куче", "автоматически" == "в стеке/регистрах", "статически" == "в специально зарезервированном линкером участке памяти, не в стеке и не в куче". Цитата(prottoss @ Jan 18 2007, 19:39)  1. Если уж говорить по русски - я считаю что "динамически" - это на этапе исполнения кода, а Вы о чем глаголите??? Пытаемся обсуждать тематический вопрос с применением принятой в этой области терминологии. Чтобы избежать несуразностей, вызванных неправильной трактовкой "пимпочек", "загогулин" и "фИгни"
--------------------
На любой вопрос даю любой ответ"Write code that is guaranteed to work, not code that doesn’t seem to break" ( C++ FAQ)
|
|
|
|
|
Jan 19 2007, 12:36
|

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

|
Цитата(Сергей Борщ @ Jan 19 2007, 16:21)  Цитата(prottoss @ Jan 18 2007, 19:39)  А в чем разница между "динамически" и "автоматически"???
"динамически" == "в куче", "автоматически" == "в стеке/регистрах", "статически" == "в специально зарезервированном линкером участке памяти, не в стеке и не в куче". Цитата(prottoss @ Jan 18 2007, 19:39)  1. Если уж говорить по русски - я считаю что "динамически" - это на этапе исполнения кода, а Вы о чем глаголите??? Пытаемся обсуждать тематический вопрос с применением принятой в этой области терминологии. Чтобы избежать несуразностей, вызванных неправильной трактовкой "пимпочек", "загогулин" и "фИгни" Да, я стараюсь избегать создания массивов внутри функции... Тем паче, что, посмотрев код, на самом деле убедился в том, что ИАР выделил место под массив в стеке данных - он просто в начале функции взял, и увеличил значение регистра Y на размер моего объявленного массива! В принципе, в х86 компиляторах делается то же самое, но там размер памяти 4 Gb, здесь же иногда приходится крутится в 128 байтах да еще с практически всеми возможными задействованными прерываниями НО, зачем тогда в опциях ИАРа стоит heap size для Си (без плюсиков) ? Оператор new использовать нет возможности, зачем же тогда куча?
--------------------
|
|
|
|
|
Jan 19 2007, 13:55
|

Шаман
     
Группа: Модераторы
Сообщений: 3 064
Регистрация: 30-06-04
Из: Киев, Украина
Пользователь №: 221

|
Цитата(prottoss @ Jan 19 2007, 12:29)  Цитата(Сергей Борщ @ Jan 19 2007, 16:57)  Цитата(prottoss @ Jan 19 2007, 11:36)  НО, зачем тогда в опциях ИАРа стоит heap size для Си (без плюсиков) ? Оператор new использовать нет возможности, зачем же тогда куча?
Чтобы размещать в ней различные данные, используя функции malloc, calloc, free и т.д. из stdlib.h. Динамическое распределение памяти Вы сами то эти функции применяете в проектах?  Я, например, применяю. Работает.
|
|
|
|
|
Jan 19 2007, 14:12
|

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

|
Цитата(IgorKossak @ Jan 19 2007, 17:55)  Цитата(prottoss @ Jan 19 2007, 12:29)  Цитата(Сергей Борщ @ Jan 19 2007, 16:57)  Цитата(prottoss @ Jan 19 2007, 11:36)  НО, зачем тогда в опциях ИАРа стоит heap size для Си (без плюсиков) ? Оператор new использовать нет возможности, зачем же тогда куча?
Чтобы размещать в ней различные данные, используя функции malloc, calloc, free и т.д. из stdlib.h. Динамическое распределение памяти Вы сами то эти функции применяете в проектах? Я, например, применяю. Работает. Интересно, что делает контроллер, когда узнает, указатель равен NULL??? наверное начинает истерично мигать лампочками
--------------------
|
|
|
|
|
Jan 20 2007, 04:48
|
Гуру
     
Группа: Свой
Сообщений: 2 712
Регистрация: 28-11-05
Из: Беларусь, Витебск, Строителей 18-4-220
Пользователь №: 11 521

|
Prottoss последний мой проект целиком построен на динамической памяти. Именно AVR правда m640 (8к озу) Фишка в том что программа в МК - это продолжение железа. И Вы и я это понимаем. NULL не может быть получен. Это говорит о том, что у Вас в проге что-то не верно. Если даже менеджер и не полный, значит вы сами должны контролировать. Я работаю с данными типа файл. Этот файл приходит с PC. Внутри данных идут упорядоченные структуры. Они нескольких типов и разной длины. Длина файла не известна. Как можно с этим работать? Только куча и указатели. Причём Вы не поверите. Я сам не поверил. Удобно до безобразия. Наглядно и красиво. Вырву кусочек. Код KomXx = (struct AddrKomXx*) AdrActiveKom[i]; // Прочитать адрес текущей активной команды if(KomXx->TimeStart>TekTime) continue; // Если не подошло время для исполнения команды, то пропустить данную команду switch (KomXx->Name) { ......... /* Команда "OUTG" - "Вывод статической графики" */ case 'G': KomG = (struct AddrKomG*) AdrActiveKom[i]; // Прочитать адрес текущей активной команды KomG->TimeMashtabTek++; // Следующий такт if(KomG->TimeMashtabTek >= KomG->TimeMashtab)// если подошёл, то KomG->TimeMashtabTek=0; // иначе начать заново OutPict(KomG->BegX,KomG->BegY,KomG->SizeX,KomG->SizeY,&KomG->Pict[0]); // Вывести картинку if(KomG->TimeMashtabTek == 0){ // если подошёл, то KomG->TimeLife--; // Уменьшить время жизни KomG->BegX += KomG->VecX; // Сместить объект KomG->BegY += KomG->VecY; // Сместить объект } break; /* Команда "ANIMATE" - "Вывод анимированной графики" */ case 'M': KomM = (struct AddrKomM*) AdrActiveKom[i]; // Прочитать адрес текущей активной команды .....
|
|
|
|
|
Jan 20 2007, 05:12
|
Гуру
     
Группа: Свой
Сообщений: 2 712
Регистрация: 28-11-05
Из: Беларусь, Витебск, Строителей 18-4-220
Пользователь №: 11 521

|
Цитата(Сергей Борщ @ Jan 19 2007, 13:06)  Где там? В куче? Зарадибога. Заметьте, вы получили указатель не "на свободное место в куче", а на свободный участок указанного вами размера. В этот участок никто больше не залезет. Но и вы не имеете права лезть за границы этого участка. Цитата(SasaVitebsk @ Jan 19 2007, 01:21)  Не зная об этом я беру и выполняю операцию OW_free(). В результате происходит крах проги. Поэтому я и высказал сомнение о реальности.
Никакого краха. В кучу возвращается выделенный вам участок, на который указывал OW_Rom_Device. Остальные участки если и были выделены кому-то без вашего ведома продолжают существовать.  Усложним задачу. Давайте в цифрах. Для простоты начальный уровень 0. Потом я занял 100. Компилятор выделил 10. Я освободил до нуля. И опять забрал кусок, на этот раз 200. И запортил его. Крах? Я не говорю что так будет. Я говорю что это у меня не уложилось в голове, и поэтому я предположил что компилятор самостоятельно не имеет права использовать кучу. Что в принципе пишите и Вы. Теперь ещё один момент. Конечно чисто теоретически поставленная мной задача(новая) вполне разрешима с хорошим менеджером кучи. Но мы то говорим о AVR. Если брать например DELFI (C для PC я не пользую), то там я имею право например выделить память под A,B,C,D а потом освободить место из под B. Потом если я выделю память под переменную E, то я не знаю где её расположит менеджер кучи. Он может её расположить за D, а может (если размеры подойдут на место дырки  . Я не в праве гадать. Если эти переменные использовать правильно, то разницы ведь нет. А объём оставшейся свободной памяти я получаю исправно. Но в IAR AVR под С такого нет! Я был удивлён. Процедурой free, я могу только освободить одну или несколько переменных от конца кучи. Я не могу освободить B! Могу только B,C,D. Да и занять я могу просто место, а не создать переменную. Вроде это есть в C++. Не знаю. Не работал ещё. Но это реально указывает на то, что менеджер очень упрощённый. Что в принципе обосновано. Если для МК делать что-то мощнее, то это будет слабо востребовано.
|
|
|
|
|
  |
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|