Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: Может ли меняться адрес переменной в стеке?
Форум разработчиков электроники ELECTRONIX.ru > Микроконтроллеры (MCs) > AVR
777777
Допустим есть такой код:
Код
bool ModulesInit(uint8_t mn)
    {
    uint8_t cmd[3] = { 8, mn, 0 };

    pTWI = cmd;
    // ...

Массив cmd[] компилятор размещает в стеке. Затем его адрес присваивается другой переменной и она с ним как-то работает, причем эта переменная используется в прерывании. В связи с этим возникает вопрос: можно ли быть уверенным, что положение этого массива в ОЗУ (его абсолютный адрес) не изменится? Разумеется, при условии что из функции мы еще не вышли. Не может ли в процессе выполнения функции он как-то двигаться? Дело в том, что в таком виде наблюдались необъяснимые глюки, которые исчезли как только я объявил этот массив static. Но они и раньше иногда исчезали, поэтому нет уверенности, что их вылечил именно static.
kolobok0
Цитата(777777 @ Oct 5 2010, 10:39) *
...можно ли быть уверенным, что положение этого массива в ОЗУ (его абсолютный адрес) не изменится? Разумеется, при условии что из функции мы еще не вышли. Не может ли в процессе выполнения функции он как-то двигаться?...


не должен.
но!
1) надо убедиться, что Вы адресуетесь _именно_к_нему_ а не по указателю на деревню бабушке.
2) (маловероятно)соглашение об очистке стэка в вызываемых подпрограммах соблюдено.
3) не происходит выхода за его размерность, при работе с ним.
4) само значение указателя ссылающегося на него не меняется

все эти случаи отсекаются под низкоуровневым дебагом. либо мало инфы привели.

(круглый)
GDI
Как вы себе представляете "движения" стека? Это вообще-то довольно нетривиальная задача сдвинуть в памяти десяток переменных разного типа, и уж тем более это задача не для АВР, и конечно-же такого ни один компилятор не делает сам. Гораздо более вероятна ошибка программиста, т.е. все 4 выше приведенных пункта.
IgorKossak
Цитата(GDI @ Oct 5 2010, 10:55) *
...Гораздо более вероятна ошибка программиста, т.е. все 4 выше приведенных пункта.

Или стек переполнился, что тоже ошибка программиста.
Или прерывание сработало после того, как программа покинула функцию.

Цитата(777777 @ Oct 5 2010, 09:39) *
Массив cmd[] компилятор размещает в стеке. Затем его адрес присваивается другой переменной и она с ним как-то работает, причем эта переменная используется в прерывании.

Оооо! Какой моветон.
777777
Цитата(IgorKossak @ Oct 5 2010, 12:24) *
Оооо! Какой моветон.

Это еще почему? Некая функция хочет послать данные по I2C. Для этого нужно указатель I2C установить на буфер из которого будут передаваться данные. Этот буфер находится в функции, поэтому создается на стеке. Ну а передаваться они, естественно, будут по прерываниям. Какие проблемы?
MrYuran
Цитата(777777 @ Oct 5 2010, 12:54) *
Это еще почему? Некая функция хочет послать данные по I2C. Для этого нужно указатель I2C установить на буфер из которого будут передаваться данные. Этот буфер находится в функции, поэтому создается на стеке. Ну а передаваться они, естественно, будут по прерываниям. Какие проблемы?

А не проще заполнить статический буфер, дать обработчику ссылку на начало и длину и спокойно заниматься своими делами?
Сергей Борщ
Цитата(777777 @ Oct 5 2010, 11:54) *
Этот буфер находится в функции, поэтому создается на стеке. Ну а передаваться они, естественно, будут по прерываниям. Какие проблемы?
Надо оставаться в функции до завершения работы прерываний. Зачем тогда прерывания?
Есть еще один тонкий момент - вы объявили буфер без volatile, поэтому если во время, пока прерывание работает с буфером функция занимается чем-то еще кроме ожидания, компилятор вполне может расположить на месте этого буфера какие-то использующиеся дальше локальные переменные, ведь с его точки зрения функция уже закончила работу с буфером и он ей больше не нужен. Более того, компилятор вправе выкинуть этот буфер и его заполнение вообще, ведь занесенные в не-volatile буфер данные дальше не используются.
777777
Цитата(MrYuran @ Oct 5 2010, 13:01) *
А не проще заполнить статический буфер, дать обработчику ссылку на начало и длину и спокойно заниматься своими делами?

А "свои дела" как раз и заключаются в том, чтобы опросить несколько модулей по I2C и передать с них информацию дальше. Поэтому пока она передается, делать все равно нечего, нужно стоять и ждать.

Цитата(Сергей Борщ @ Oct 5 2010, 14:19) *
Есть еще один тонкий момент - вы объявили буфер без volatile, поэтому если во время, пока прерывание работает с буфером функция занимается чем-то еще кроме ожидания, компилятор вполне может расположить на месте этого буфера какие-то использующиеся дальше локальные переменные, ведь с его точки зрения функция уже закончила работу с буфером и он ей больше не нужен. Более того, компилятор вправе выкинуть этот буфер и его заполнение вообще, ведь занесенные в не-volatile буфер данные дальше не используются.

Обработчик прерываний ничего не знает о буферах, он работает с переменной pTWI, а она volatile. И вообще, я уже сделал буфер static, но это не помогло, глюки продолжаются, так что вопрос снимается.
prottoss
Цитата(777777 @ Oct 5 2010, 13:39) *
Но они и раньше иногда исчезали, поэтому нет уверенности, что их вылечил именно static.
Как только Вы объявили переменную как static внутри функции, переменная перестала быть стековым объектом, теперь она располагается по совершенно конкретному неизменяемому адресу в области памяти данных.
777777
Цитата(prottoss @ Oct 5 2010, 15:10) *
Как только Вы объявили переменную как static внутри функции, переменная перестала быть стековым объектом, теперь она располагается по совершенно конкретному неизменяемому адресу в области памяти данных.

Спасибо, кэп!
kolobok0
Цитата(777777 @ Oct 5 2010, 18:33) *
Спасибо, кэп!


если под дебагом не охота возится - есть другой ломовой способ.
выключаете кусок кода. помогло? да-нет. если да - подключаете кусок кода, делите его лапополам. одну половину выключаете. операцию повторяете. если не помогло - следующий кусок кода откусываете.
если после всех манипуляций у вас получилось строчек 10 кода, а всё остальное коменты - вот их (все 10) и выкладывайте сюда для помощи. а то как то гадания от телепатии уже пошли.


(круглый)
Сергей Борщ
Цитата(777777 @ Oct 5 2010, 13:44) *
Обработчик прерываний ничего не знает о буферах, он работает с переменной pTWI, а она volatile.
Да при чем тут обработчик? Функция не знает, что этот буфер еще кому-то нужен, пусть на него хоть 10 volatile-указателей указывают.
Itch
все дело в волшебном словечке volatile

Программист, запомни!
Если ТЫ используешь прерывания и разделяемые переменные,
То обязательно напиши это волшебное слово volatile.
И прибудет тогда с тобой сила!
halfdoom
Цитата(Сергей Борщ @ Oct 5 2010, 20:14) *
Функция не знает, что этот буфер еще кому-то нужен, пусть на него хоть 10 volatile-указателей указывают.

Точнее, _компилятор_ не знает, что этот буфер еще нужен, и имеет полное право использовать под другие переменные в данной функции.
Сергей Борщ
Цитата(halfdoom @ Oct 6 2010, 07:59) *
Точнее, _компилятор_ не знает,
Это я писал в сообщении №7. Тут попытался упростить.
777777
Цитата(Сергей Борщ @ Oct 6 2010, 12:56) *
Это я писал в сообщении №7. Тут попытался упростить.

Господа, вопрос давно снят. Глюк найден в другом модуле, он передавался с данными, а эта функция его исправно принимала и транслировала дальше.
Сергей Борщ
Цитата(777777 @ Oct 6 2010, 12:19) *
Господа, вопрос давно снят. Глюк найден в другом модуле
Теперь будете ждать, пока отсутствие volatile "выстрелит" в какой-нибудь очередной версии компилятора в связи с улучшением оптимизатора в нем?
777777
Цитата(Сергей Борщ @ Oct 6 2010, 17:13) *
Теперь будете ждать, пока отсутствие volatile "выстрелит" в какой-нибудь очередной версии компилятора в связи с улучшением оптимизатора в нем?

Я же написал, что объявил ее static, вы ведь не будете утверждать что этого не достаточно? Но и в старом варианте ничего бы не случилось: она используется до конца функции и функция не выполняет возврат пока передача не закончится.
Сергей Борщ
Цитата(777777 @ Oct 6 2010, 17:47) *
Я же написал, что объявил ее static, вы ведь не будете утверждать что этого не достаточно?
Буду. Оптимизатор вполне может выкинуть запись в любую переменную, будь то обычный int или массив, если он видит, что результат такой записи не используется (а с его точки зрения он не используется). Если он еще не выкинул эту запись - у него недостаточно продвинутый оптимизатор. Единственный способ 100% заставить компилятор писать - объявить массив как volatile. Я не заставляю вас это делать, просто предупреждаю что с какой-то из следующих версий компилятора ваш код может перестать работать на, казалось бы, ровном месте.
kolobok0
(бормоча се под нос на ночь глядя)
от посему обожаю азм. что написал = сам дурак.

а тут вот человек уже сколько время потратил в холостую то!!! можно было бы экранов 10 уже настрочить на азме smile.gif и вообще забот не знать.


(круглый)
ЗЫ
Только не воспринимайте это как спор, что лучше....
Ink
Цитата(kolobok0 @ Oct 7 2010, 00:54) *
от посему обожаю азм. что написал = сам дурак.

если человек не знает инструмент, с которым работает = сам дурак. не принципиально, асм это или не асм.
IgorKossak
Поскольку вопрос снят и так прекрасно всё закончилось, тему закрываю.
Модератор
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.