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

 
 
5 страниц V  < 1 2 3 4 5 >  
Reply to this topicStart new topic
> перезапуск программы, непонятно почему.
Dan_Dima
сообщение Jan 18 2007, 14:35
Сообщение #31


Участник
*

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



Цитата(Dog Pawlowa @ Jan 18 2007, 13:00) *
Цитата(Dan_Dima @ Jan 18 2007, 13:28) *

Насколько я помню подобные преобразования компилятор делает сам ( только проверил) так как преобразование идет к "большему" типу. Поэтому эти две записи эквивалентны.

Конечно сам, но на каком этапе?
Отличие в записях в моменте преобразования.


Преобразование происходит по ходу выполнения вычислений если говорить о том как это делаеться в обычном С. В IAR может действительно надо принудительно описывать привидение типов в том же gcc такого нет.
Go to the top of the page
 
+Quote Post
Dog Pawlowa
сообщение Jan 18 2007, 18:08
Сообщение #32


Гуру
******

Группа: Свой
Сообщений: 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.


--------------------
Уходя, оставьте свет...
Go to the top of the page
 
+Quote Post
Сергей Борщ
сообщение Jan 18 2007, 18:56
Сообщение #33


Гуру
******

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



Цитата(SasaVitebsk @ Jan 17 2007, 23:49) *
Но я говорю немного уклончиво потому, что полностью компилятор не знает никто кроме разработчиков, а в полной мере проверить не удаётся.
Для того и существуют стандарты, чтобы точно описывать "как оно должно быть","как оно не должно быть" и "а вот это хз". Последнее отдано на откуп разработчикам компиляторов. Не больше.
Цитата(SasaVitebsk @ Jan 17 2007, 23:49) *
Пример специально для Вас Сергей Борщ. smile.gif В библиотеках которые я выкладывал по поводу 18b20 применено динамическое распределение памяти. И там же использован массив локальный.
Здесь вы путаетесь в терминах. В языке С динамическим распределением памяти называется именно работа с кучей. Локальные переменные, под которые память выделяется на стеке, в терминах С называются автоматическими. Переменные, под которые память выделяется на этапе запуска программы, называются статическими. К статическим относятся глобальные переменные и локальные переменные, объявленные с квалификатором static. В вашем примере динамического распределения я не увидел.
Цитата(SasaVitebsk @ Jan 17 2007, 23:49) *
Возможно Вы будете удивлены, но IAR данный массив размещает в регистрах. (Оптимизирует)
Ненаказуемо smile.gif Но если вы попытаетесь взять адрес такой переменной и передать куда-либо указатель на нее, она сразу же из регистров окажется в памяти.

Цитата(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)
Go to the top of the page
 
+Quote Post
prottoss
сообщение Jan 18 2007, 19:40
Сообщение #34


Гуру
******

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



defunct был прав - массив, объявленный в функции, создается не в куче, а в стеке данных (я говрю про ИАР). Проверил листинг ассемблера - все так и есть. Единственное, в чем я был прав - массив, объявленный в функции - создается динамически!!! Так что, ребята, учитывайте это при создании приложений для АВР на ИАР angry.gif .


--------------------
Go to the top of the page
 
+Quote Post
zltigo
сообщение Jan 18 2007, 20:15
Сообщение #35


Гуру
******

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



Цитата(prottoss @ Jan 18 2007, 18:40) *
Единственное, в чем я был прав - массив, объявленный в функции - создается динамически!!!

Нет, не "динамически" а "автоматически" - Сергей уже обьяснял!!!
Цитата
Так что, ребята, учитывайте это при создании приложений для АВР на ИАР angry.gif .

Ни AVR, ни IAR здесь ни причем. "С", просто "С" стандартное поведение.


--------------------
Feci, quod potui, faciant meliora potentes
Go to the top of the page
 
+Quote Post
prottoss
сообщение Jan 18 2007, 20:39
Сообщение #36


Гуру
******

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



Цитата(zltigo @ Jan 19 2007, 00:15) *
Цитата(prottoss @ Jan 18 2007, 18:40) *

Единственное, в чем я был прав - массив, объявленный в функции - создается динамически!!!

Нет, не "динамически" а "автоматически" - Сергей уже обьяснял!!!
Цитата
Так что, ребята, учитывайте это при создании приложений для АВР на ИАР angry.gif .

Ни AVR, ни IAR здесь ни причем. "С", просто "С" стандартное поведение.


А в чем разница между "динамически" и "автоматически"???

1. Если уж говорить по русски - я считаю что "динамически" - это на этапе исполнения кода, а Вы о чем глаголите???

2. Про стандартное поведение Си согласен, здесь все четко


--------------------
Go to the top of the page
 
+Quote Post
xemul
сообщение Jan 18 2007, 21:15
Сообщение #37



*****

Группа: Свой
Сообщений: 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: извините за невольный частичный повтор - писАлось больше часа, задергали звонками и неотложными проблемами.
Go to the top of the page
 
+Quote Post
prottoss
сообщение Jan 18 2007, 21:43
Сообщение #38


Гуру
******

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



Канешна, это все здорово очень, объясните тада, умные сотоварищи, зачем мне указывать размер стека данных, еслиФ все равно компилятор и иже с ними, создаст массив в этом самом стекеданных, то бишь нарушит мое НЕОСПОРИМОЕ правило???


--------------------
Go to the top of the page
 
+Quote Post
xemul
сообщение Jan 18 2007, 21:44
Сообщение #39



*****

Группа: Свой
Сообщений: 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) *

Единственное, в чем я был прав - массив, объявленный в функции - создается динамически!!!

Нет, не "динамически" а "автоматически" - Сергей уже обьяснял!!!
Цитата
Так что, ребята, учитывайте это при создании приложений для АВР на ИАР angry.gif .

Ни AVR, ни IAR здесь ни причем. "С", просто "С" стандартное поведение.

А в чем разница между "динамически" и "автоматически"???

Автоматическая переменная будет удалена автоматически при выходе из функции, в которой она была определена.
Удаление динамических переменных по мере их ненадобности - задача программера. Распространненость подобных ошибок (неосвобождение памяти) приводилась как аргумент за корявость всего языка.
Go to the top of the page
 
+Quote Post
prottoss
сообщение Jan 18 2007, 21:52
Сообщение #40


Гуру
******

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



Цитата(xemul @ Jan 19 2007, 01:44) *
Автоматическая переменная будет удалена автоматически при выходе из функции, в которой она была определена.
А что, она будет создана не динамически?


--------------------
Go to the top of the page
 
+Quote Post
xemul
сообщение Jan 18 2007, 21:59
Сообщение #41



*****

Группа: Свой
Сообщений: 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) *
Автоматическая переменная будет удалена автоматически при выходе из функции, в которой она была определена.
А что, она будет создана не динамически?

Вы просили объяснить разницу между автоматическими и динамическими объектами в терминологии С.
А в жизни вообще все относительно - статические объекты с точки зрения программы существуют всегда, а с точки зрения ОС - только пока живет программа. Считать их динамическими?
Go to the top of the page
 
+Quote Post
prottoss
сообщение Jan 18 2007, 22:04
Сообщение #42


Гуру
******

Группа: Свой
Сообщений: 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) *
Вы же можете среднепотолочно прикинуть требуемый размер стека
Гон всезнайки????????????????????????


--------------------
Go to the top of the page
 
+Quote Post
xemul
сообщение Jan 19 2007, 00:20
Сообщение #43



*****

Группа: Свой
Сообщений: 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) *
Вы же можете среднепотолочно прикинуть требуемый размер стека
Гон всезнайки????????????????????????

Вам не доводилось этим заниматься и установки стека по умолчанию достаточно? Ну и слава богу и разработчикам используемых Вами компиляторов.
Если помните, причина возникновения этого треда крылась в некорректной работе со стеком. Подобные треды возникают достаточно регулярно, и в них неоднократно обсуждались способы контроля переполнения и оценки требуемой глубины стека. Кста, Вы в них активно участвовали. Не отложилось?
И, плз, если Вы чего-то не знаете, не выставляйте это напоказ несколько агрессивным образом.
Go to the top of the page
 
+Quote Post
defunct
сообщение Jan 19 2007, 01:32
Сообщение #44


кекс
******

Группа: Свой
Сообщений: 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 и он опять вернется в "кучу".
Go to the top of the page
 
+Quote Post
SasaVitebsk
сообщение Jan 19 2007, 02:21
Сообщение #45


Гуру
******

Группа: Свой
Сообщений: 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) *
Пример специально для Вас Сергей Борщ. smile.gif В библиотеках которые я выкладывал по поводу 18b20 применено динамическое распределение памяти. И там же использован массив локальный.
Здесь вы путаетесь в терминах. В языке С динамическим распределением памяти называется именно работа с кучей. Локальные переменные, под которые память выделяется на стеке, в терминах С называются автоматическими. Переменные, под которые память выделяется на этапе запуска программы, называются статическими. К статическим относятся глобальные переменные и локальные переменные, объявленные с квалификатором static. В вашем примере динамического распределения я не увидел.
Цитата(SasaVitebsk @ Jan 17 2007, 23:49) *
Возможно Вы будете удивлены, но IAR данный массив размещает в регистрах. (Оптимизирует)
Ненаказуемо smile.gif Но если вы попытаетесь взять адрес такой переменной и передать куда-либо указатель на нее, она сразу же из регистров окажется в памяти.

Цитата(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. Таким образом менеджер памяти там очень мощный. Он может перераспределять данные, в том числе от разных пользователей/потоков. Здесь менеджер - один указатель и пара сравнений. Написано пользователь сам должен. Оно и понятно "обеднённая" система.
Go to the top of the page
 
+Quote Post

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

 


RSS Текстовая версия Сейчас: 19th July 2025 - 09:20
Рейтинг@Mail.ru


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