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

 
 
2 страниц V   1 2 >  
Closed TopicStart new topic
> Может ли меняться адрес переменной в стеке?
777777
сообщение Oct 5 2010, 06:39
Сообщение #1


Профессионал
*****

Группа: Участник
Сообщений: 1 091
Регистрация: 25-07-07
Из: Саратов
Пользователь №: 29 357



Допустим есть такой код:
Код
bool ModulesInit(uint8_t mn)
    {
    uint8_t cmd[3] = { 8, mn, 0 };

    pTWI = cmd;
    // ...

Массив cmd[] компилятор размещает в стеке. Затем его адрес присваивается другой переменной и она с ним как-то работает, причем эта переменная используется в прерывании. В связи с этим возникает вопрос: можно ли быть уверенным, что положение этого массива в ОЗУ (его абсолютный адрес) не изменится? Разумеется, при условии что из функции мы еще не вышли. Не может ли в процессе выполнения функции он как-то двигаться? Дело в том, что в таком виде наблюдались необъяснимые глюки, которые исчезли как только я объявил этот массив static. Но они и раньше иногда исчезали, поэтому нет уверенности, что их вылечил именно static.
Go to the top of the page
 
+Quote Post
kolobok0
сообщение Oct 5 2010, 07:32
Сообщение #2


практикующий тех. волшебник
*****

Группа: Участник
Сообщений: 1 190
Регистрация: 9-09-05
Пользователь №: 8 417



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


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

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

(круглый)
Go to the top of the page
 
+Quote Post
GDI
сообщение Oct 5 2010, 07:55
Сообщение #3


Профессионал
*****

Группа: Свой
Сообщений: 1 235
Регистрация: 14-05-05
Из: Санкт-Петербург
Пользователь №: 5 008



Как вы себе представляете "движения" стека? Это вообще-то довольно нетривиальная задача сдвинуть в памяти десяток переменных разного типа, и уж тем более это задача не для АВР, и конечно-же такого ни один компилятор не делает сам. Гораздо более вероятна ошибка программиста, т.е. все 4 выше приведенных пункта.


--------------------
http://www.embedders.org Блоги разработчиков электроники.
Go to the top of the page
 
+Quote Post
IgorKossak
сообщение Oct 5 2010, 08:24
Сообщение #4


Шаман
******

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



Цитата(GDI @ Oct 5 2010, 10:55) *
...Гораздо более вероятна ошибка программиста, т.е. все 4 выше приведенных пункта.

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

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

Оооо! Какой моветон.
Go to the top of the page
 
+Quote Post
777777
сообщение Oct 5 2010, 08:54
Сообщение #5


Профессионал
*****

Группа: Участник
Сообщений: 1 091
Регистрация: 25-07-07
Из: Саратов
Пользователь №: 29 357



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

Это еще почему? Некая функция хочет послать данные по I2C. Для этого нужно указатель I2C установить на буфер из которого будут передаваться данные. Этот буфер находится в функции, поэтому создается на стеке. Ну а передаваться они, естественно, будут по прерываниям. Какие проблемы?
Go to the top of the page
 
+Quote Post
MrYuran
сообщение Oct 5 2010, 09:01
Сообщение #6


Беспросветный оптимист
******

Группа: Свой
Сообщений: 4 640
Регистрация: 26-12-07
Из: Н.Новгород
Пользователь №: 33 646



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

А не проще заполнить статический буфер, дать обработчику ссылку на начало и длину и спокойно заниматься своими делами?


--------------------
Программирование делится на системное и бессистемное. ©Моё :)
— а для кого-то БГ — это Bill Gilbert =)
Go to the top of the page
 
+Quote Post
Сергей Борщ
сообщение Oct 5 2010, 10:19
Сообщение #7


Гуру
******

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



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


--------------------
На любой вопрос даю любой ответ
"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
777777
сообщение Oct 5 2010, 10:44
Сообщение #8


Профессионал
*****

Группа: Участник
Сообщений: 1 091
Регистрация: 25-07-07
Из: Саратов
Пользователь №: 29 357



Цитата(MrYuran @ Oct 5 2010, 13:01) *
А не проще заполнить статический буфер, дать обработчику ссылку на начало и длину и спокойно заниматься своими делами?

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

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

Обработчик прерываний ничего не знает о буферах, он работает с переменной pTWI, а она volatile. И вообще, я уже сделал буфер static, но это не помогло, глюки продолжаются, так что вопрос снимается.
Go to the top of the page
 
+Quote Post
prottoss
сообщение Oct 5 2010, 11:10
Сообщение #9


Гуру
******

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



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


--------------------
Go to the top of the page
 
+Quote Post
777777
сообщение Oct 5 2010, 14:33
Сообщение #10


Профессионал
*****

Группа: Участник
Сообщений: 1 091
Регистрация: 25-07-07
Из: Саратов
Пользователь №: 29 357



Цитата(prottoss @ Oct 5 2010, 15:10) *
Как только Вы объявили переменную как static внутри функции, переменная перестала быть стековым объектом, теперь она располагается по совершенно конкретному неизменяемому адресу в области памяти данных.

Спасибо, кэп!
Go to the top of the page
 
+Quote Post
kolobok0
сообщение Oct 5 2010, 16:50
Сообщение #11


практикующий тех. волшебник
*****

Группа: Участник
Сообщений: 1 190
Регистрация: 9-09-05
Пользователь №: 8 417



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


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


(круглый)

Сообщение отредактировал kolobok0 - Oct 5 2010, 16:50
Go to the top of the page
 
+Quote Post
Сергей Борщ
сообщение Oct 5 2010, 17:14
Сообщение #12


Гуру
******

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



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


--------------------
На любой вопрос даю любой ответ
"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
Itch
сообщение Oct 6 2010, 03:41
Сообщение #13


Местный
***

Группа: Свой
Сообщений: 358
Регистрация: 27-06-06
Из: Новосибирск
Пользователь №: 18 410



все дело в волшебном словечке volatile

Программист, запомни!
Если ТЫ используешь прерывания и разделяемые переменные,
То обязательно напиши это волшебное слово volatile.
И прибудет тогда с тобой сила!
Go to the top of the page
 
+Quote Post
halfdoom
сообщение Oct 6 2010, 04:59
Сообщение #14


Профессионал
*****

Группа: Свой
Сообщений: 1 003
Регистрация: 20-01-05
Пользователь №: 2 072



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

Точнее, _компилятор_ не знает, что этот буфер еще нужен, и имеет полное право использовать под другие переменные в данной функции.
Go to the top of the page
 
+Quote Post
Сергей Борщ
сообщение Oct 6 2010, 08:56
Сообщение #15


Гуру
******

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



Цитата(halfdoom @ Oct 6 2010, 07:59) *
Точнее, _компилятор_ не знает,
Это я писал в сообщении №7. Тут попытался упростить.


--------------------
На любой вопрос даю любой ответ
"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

2 страниц V   1 2 >
Closed TopicStart new topic
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0

 


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


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