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

 
 
2 страниц V   1 2 >  
Reply to this topicStart new topic
> Странная проблема с переменными, или как пользоваться volatile
Spider
сообщение Aug 6 2008, 13:46
Сообщение #1


В поисках истины
***

Группа: Свой
Сообщений: 431
Регистрация: 7-01-06
Из: Россия
Пользователь №: 12 923



Чудесным образом портится память. Стал выяснять что же не так и не пойму.
Возник вопрос каксающийся volatile.
Есть ли разница в следующем и какая?
Код
typedef struct TSTRUCT
{
  volatile u8 *DATABuff;
  volatile u8 *CMDBuff;
} T_STRUCT;

volatile T_STRUCT STRUCT;
и вариант
Код
typedef struct TSTRUCT
{
  u8 *DATABuff;
  u8 *CMDBuff;
} T_STRUCT;

volatile T_STRUCT STRUCT;
Какова будет разница? есть ли тут смысл?
Go to the top of the page
 
+Quote Post
rezident
сообщение Aug 6 2008, 13:55
Сообщение #2


Гуру
******

Группа: Свой
Сообщений: 10 920
Регистрация: 5-04-05
Пользователь №: 3 882



Разница есть, только смысла в ней нету smile.gif
А память портится скорее всего потому, что вы где-то пренебрегаете проверкой на выход значений указателей за границы выделенных им буферов.
Go to the top of the page
 
+Quote Post
Сергей Борщ
сообщение Aug 6 2008, 13:58
Сообщение #3


Гуру
******

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



В первом случае у вас может (неизвестным для компилятора образом) измениться то, на что указывает указатель в структуре. во втором случае - сам указатель.

P.S. Вообще интересная постановка вопроса: "А что же я понаписал?" Может стоить формулировать его несколько иначе: "Мне надо чтобы было так-то. Как это сделать?"


--------------------
На любой вопрос даю любой ответ
"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
defunct
сообщение Aug 6 2008, 14:17
Сообщение #4


кекс
******

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



Цитата(Сергей Борщ @ Aug 6 2008, 16:58) *
P.S. Вообще интересная постановка вопроса: "А что же я понаписал?" Может стоить формулировать его несколько иначе: "Мне надо чтобы было так-то. Как это сделать?"

При memory corruption bug'ах не до постановки "Мне надо чтобы...", потому что неизвестно что надо на самом деле..
Автор может сказать лишь - "Мне надо чтобы не глючило".

Цитата
есть ли тут смысл?

Смысла в volatile'ях тут нет, как перед полями структуры так и перед объявлением самой структуры.

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

Чем больше статистических данных получите, тем проще будет локализовать блок вызывающий повреждения.
Go to the top of the page
 
+Quote Post
MrYuran
сообщение Aug 6 2008, 14:23
Сообщение #5


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

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



данные могут портиться при нарушении выравнивания слов. У меня однажды указатели на int каким-то чудесным образом указывали между этих самых интов, и модификация одной переменной портила вторую (да и первую тоже).
В структурах надо аккуратнее с выравниванием и указателями


--------------------
Программирование делится на системное и бессистемное. ©Моё :)
— а для кого-то БГ — это Bill Gilbert =)
Go to the top of the page
 
+Quote Post
Spider
сообщение Aug 6 2008, 14:25
Сообщение #6


В поисках истины
***

Группа: Свой
Сообщений: 431
Регистрация: 7-01-06
Из: Россия
Пользователь №: 12 923



Цитата(defunct @ Aug 6 2008, 21:17) *
Автор может сказать лишь - "Мне надо чтобы не глючило".
Смысла в volatile'ях тут нет, как перед полями структуры так и перед объявлением самой структуры.

Почему? Точнее почему нет смыла перед объявлением самой структуры?
Go to the top of the page
 
+Quote Post
defunct
сообщение Aug 6 2008, 14:31
Сообщение #7


кекс
******

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



Цитата(Alexey Belyaev @ Aug 6 2008, 17:25) *
Почему? Точнее почему нет смыла перед объявлением самой структуры?

Потому что компилятор обычно не опускает обращения к полям структур и так. Да и не видя кода где такая структура используется volatile - теряют весь смысл.
У вас указатели в ней могут произвольно меняться скажем "железом" или еще каким-то странным образом?

Цитата
данные могут портиться при нарушении выравнивания слов.

Не могут - ШД 8-ми битная.
Это не ARM.
Go to the top of the page
 
+Quote Post
Spider
сообщение Aug 7 2008, 02:06
Сообщение #8


В поисках истины
***

Группа: Свой
Сообщений: 431
Регистрация: 7-01-06
Из: Россия
Пользователь №: 12 923



Цитата(defunct @ Aug 6 2008, 21:31) *
Потому что компилятор обычно не опускает обращения к полям структур и так. Да и не видя кода где такая структура используется volatile - теряют весь смысл.
В основном структура передаётся в функции как указатель на неё.
Код
foo(T_STRUCT *S);
И ещё делаю memcpy().
Цитата(defunct @ Aug 6 2008, 21:31) *
У вас указатели в ней могут произвольно меняться скажем "железом" или еще каким-то странным образом?

:\ А как "железо" может сменить указатель? smile.gif Нет.
Go to the top of the page
 
+Quote Post
SysRq
сообщение Aug 7 2008, 02:33
Сообщение #9


Чайник, 1 литр
****

Группа: Свой
Сообщений: 655
Регистрация: 17-05-06
Из: Moscow
Пользователь №: 17 168



Цитата(defunct @ Aug 6 2008, 18:17) *
Расскажите больше о характере повреждений.

+1

А sizeof() используете? Внимательно проверьте где и как.
Go to the top of the page
 
+Quote Post
Spider
сообщение Aug 7 2008, 04:21
Сообщение #10


В поисках истины
***

Группа: Свой
Сообщений: 431
Регистрация: 7-01-06
Из: Россия
Пользователь №: 12 923



Цитата(SysRq @ Aug 7 2008, 09:33) *
Цитата(defunct @ Aug 6 2008, 18:17) *

Расскажите больше о характере повреждений

+1
А sizeof() используете? Внимательно проверьте где и как.

К примеру есть переменная uint8_t *InitString;
В практически самом начале программы, на неё аллочится память примерно так:
Код
uint8_t *InitString;
....
len=strlen(TempBuffer+Offset);
InitString=(uint8_t *)malloc(len);
strcpy(InitString,TempBuffer+Offset);
...
И всё ровно, пока не произойдёт нечто. К примеру содержимое строки было "AT+IFC=2,2\r\n" и первое и второе и даже третее обращение к ней именно это и получало, но после чего-то содержимое строки может стать "подбитым" к примеру таким "AT+I@C*2,2\r\n". И это только частный пример. Бывает что просто переменная uint8_t внутри структуры сменила своё значение.

Я сейчас занимаюсь выводом в дебаг инфы при обращении к указателям, дабы исключить обращения "не туда". Но на глаз по коду тут всё ровно.
Go to the top of the page
 
+Quote Post
Непомнящий Евген...
сообщение Aug 7 2008, 05:32
Сообщение #11


Знающий
****

Группа: Свой
Сообщений: 771
Регистрация: 16-07-07
Из: Волгодонск
Пользователь №: 29 153



размер кучи достаточен? Куча часом не до стека идет? Может стек переполняется?
Go to the top of the page
 
+Quote Post
Spider
сообщение Aug 7 2008, 06:03
Сообщение #12


В поисках истины
***

Группа: Свой
Сообщений: 431
Регистрация: 7-01-06
Из: Россия
Пользователь №: 12 923



Цитата(Непомнящий Евгений @ Aug 7 2008, 12:32) *
размер кучи достаточен? Куча часом не до стека идет? Может стек переполняется?

Только не кидайте гнилыми помидорами, а где это глянуть?
Использую WinAVR.
Go to the top of the page
 
+Quote Post
sigmaN
сообщение Aug 7 2008, 06:20
Сообщение #13


I WANT TO BELIEVE
******

Группа: Свой
Сообщений: 2 617
Регистрация: 9-03-08
Пользователь №: 35 751



Я не пользовался WinAVR, но называется это обычно heap size для кучи и stack size для стека ))

volatile действительно не имеет смысла.
Просмотрите внимательно ещё раз весь код.
Может быть как-то прогнать пошагово и попытаться определить где именно косяк?


--------------------
The truth is out there...
Go to the top of the page
 
+Quote Post
Spider
сообщение Aug 7 2008, 06:29
Сообщение #14


В поисках истины
***

Группа: Свой
Сообщений: 431
Регистрация: 7-01-06
Из: Россия
Пользователь №: 12 923



Цитата(sigmaN @ Aug 7 2008, 13:20) *
Я не пользовался WinAVR, но называется это обычно heap size для кучи и stack size для стека ))

volatile действительно не имеет смысла.
Просмотрите внимательно ещё раз весь код.
Может быть как-то прогнать пошагово и попытаться определить где именно косяк?

для инициализации внешней памяти использую рекомендацию из WinAVR:
-Wl,--defsym=__heap_start=0x801100,--defsym=__heap_end=0x807FFF
т.е. 32к во внешней. Всё остальное не изменно.
Go to the top of the page
 
+Quote Post
Сергей Борщ
сообщение Aug 7 2008, 07:46
Сообщение #15


Гуру
******

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



Цитата(Alexey Belyaev @ Aug 7 2008, 09:29) *
т.е. 32к во внешней. Всё остальное не изменно.
А не может сбоить сама внешняя память? Попробуйте какой-нибудь тест написать (записать псевдослучайную последовательность и считывать ее в цикле, считая сбои), может программа и не виновата.
Цитата(Alexey Belyaev @ Aug 7 2008, 05:06) *
:\ А как "железо" может сменить указатель? smile.gif
Может. Самый простой пример - указатель стека. Более сложный - регистры адреса источника и приемника при ПДП (DMA). Софтовые варианты - указатель изменяется в прерывании. Или еще один случай - многопоточное приложение, доступ к указателю в разных потоках.

volatile перед стуктурой распространяет 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
Spider
сообщение Aug 7 2008, 08:16
Сообщение #16


В поисках истины
***

Группа: Свой
Сообщений: 431
Регистрация: 7-01-06
Из: Россия
Пользователь №: 12 923



Цитата(Сергей Борщ @ Aug 7 2008, 14:46) *
А не может сбоить сама внешняя память? Попробуйте какой-нибудь тест написать (записать псевдослучайную последовательность и считывать ее в цикле, считая сбои), может программа и не виновата.
Написано, всё ровно. Да и на другой железяке с этой прошивкой точно такие же сбои.
Цитата(Сергей Борщ @ Aug 7 2008, 14:46) *
Может. Самый простой пример - указатель стека. Более сложный - регистры адреса источника и приемника при ПДП (DMA). Софтовые варианты - указатель изменяется в прерывании. Или еще один случай - многопоточное приложение, доступ к указателю в разных потоках.
Ну многопоточность исключена smile.gif А по поводу изменения в прерываниях, то тут я уже однажды натыкался, и сейчас если и используется одна и та же переменная как в прерывании, так и в основном коде, то доступ к ней осуществляется только через остановку всех прерываний.
Go to the top of the page
 
+Quote Post
XVR
сообщение Aug 7 2008, 08:23
Сообщение #17


Гуру
******

Группа: Свой
Сообщений: 3 123
Регистрация: 7-04-07
Из: Химки
Пользователь №: 26 847



Цитата(Alexey Belyaev @ Aug 7 2008, 08:21) *
К примеру есть переменная uint8_t *InitString;
В практически самом начале программы, на неё аллочится память примерно так:
Код
uint8_t *InitString;
....
len=strlen(TempBuffer+Offset);
InitString=(uint8_t *)malloc(len);
strcpy(InitString,TempBuffer+Offset);
...
И всё ровно, пока не произойдёт нечто.
Уже произошло sad.gif

Код
InitString=(uint8_t *)malloc(len+1);
strlen возвращает длинну строки не считая завершающего нуля, strcpy копирует включая завершающий нуль, затирая при этом байт за пределами выделенной через malloc памяти
Go to the top of the page
 
+Quote Post
Spider
сообщение Aug 7 2008, 08:40
Сообщение #18


В поисках истины
***

Группа: Свой
Сообщений: 431
Регистрация: 7-01-06
Из: Россия
Пользователь №: 12 923



Цитата(XVR @ Aug 7 2008, 15:23) *
Уже произошло sad.gif

Код
InitString=(uint8_t *)malloc(len+1);
strlen возвращает длинну строки не считая завершающего нуля, strcpy копирует включая завершающий нуль, затирая при этом байт за пределами выделенной через malloc памяти

на самом деле это так, для примера, там ещё есть такое:
Код
len = strlen(TempBuffer+Offset)+3;
...
InitString[len-3]='\r';
InitString[len-2]='\n';
InitString[len-1]=0;
Go to the top of the page
 
+Quote Post
Spider
сообщение Aug 7 2008, 10:36
Сообщение #19


В поисках истины
***

Группа: Свой
Сообщений: 431
Регистрация: 7-01-06
Из: Россия
Пользователь №: 12 923



Ну вот. Не знаю что сделал, но глюк стал стабилен. Всегда один и тот же адрес памяти на всегда одно и то же значение. Теперь можно как-нить вычленить кто это делает?
Go to the top of the page
 
+Quote Post
defunct
сообщение Aug 7 2008, 10:52
Сообщение #20


кекс
******

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



Цитата(Alexey Belyaev @ Aug 7 2008, 07:21) *
может стать "подбитым" к примеру таким "AT+I@C*2,2\r\n".

Это похоже на сбои железа (в обоих случаях поврежден 1 бит).
Если используется вняшняя память - увеличте задержки шины.
Go to the top of the page
 
+Quote Post
Spider
сообщение Aug 7 2008, 11:45
Сообщение #21


В поисках истины
***

Группа: Свой
Сообщений: 431
Регистрация: 7-01-06
Из: Россия
Пользователь №: 12 923



Цитата(defunct @ Aug 7 2008, 17:52) *
Это похоже на сбои железа (в обоих случаях поврежден 1 бит).
Если используется вняшняя память - увеличте задержки шины.

ну да... странно конечно, почему тогда всегда одно и то же место в всегда одно и то же значение?
сейчас так:
Было: AT +IFC=2,2 +IPR=115200
Стало: AT +IFC=2,2 «IPR=115200
0x2B изменилось на 0xAB, по сути старший бит стал 1. И уже раз 8 из 8ми было именно так.

ЗЫ. bb-offtopic.gif какие должны быть задержки для 70n памяти и 8MHz проца?

Перепробовал все задержки шины, эффект остался.
Пока пробовал урезал функционал, пока не перестанет проявляться баг.
Нашёл эдакую середину. Как все могли заметить, то работаю я с GSM модемом. Так вот, если убрать совсем дозвон куда либо, а оставить только инициализацию модема и прочий функционал программы, то всё работает. Достаточно заставить модем звонить куда-либо, то после 2ого (!!!) звонка, строка инициализации карёжится.
За первый раз как-будто не добирается указатель до неёsmile.gif
Go to the top of the page
 
+Quote Post
defunct
сообщение Aug 7 2008, 12:53
Сообщение #22


кекс
******

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



Цитата(Alexey Belyaev @ Aug 7 2008, 14:45) *
Перепробовал все задержки шины, эффект остался.

Что-то не так с разводкой или с МС памяти.
Основываясь на Вашем последнем посте определенно точно можно сказать, что с адресными линиями все Ок (с защелкой в т.ч. все Ок - защелка работает).

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

Теоретически для тактирования 8Mhz и 70ns памяти, задержки могуть быть нулевые, но тут может влиять разводка (паразитные емкости растягивают фронты). Поэтому для теста установить макс задержку и посмотреть осциллографом форму сигналов на линиях данных. Еще, если сигнальные линии подключены к шине через резисторы - последние убрать, вместо них поставить перемычки или нулевки.

Цитата
Достаточно заставить модем звонить куда-либо, то после 2ого (!!!) звонка, строка инициализации карёжится.

Что за модем? Может быть модем фонит на шину данных?
Отключите модем от тел. линии и попробуйте звонить, испортятся ли данные в этом случае также?

Цитата
Так вот, если убрать совсем дозвон куда либо, а оставить только инициализацию модема и прочий функционал программы, то всё работает.

Пардон пропустил мимо ушей что модем GSM, тогда он фонит еще серьезнее. Однозначно ШД забивается помехами - попробуйте разместить модем как можно дальше от устройства. Поставить экраны (напр для теста обмотать девайс паралоном, а сверху фольгой). Если подтвердится, боюсь придется переделывать разводку полностью. Также проверьте не затягивается ли фронт сигнала "R" (хотя если бы дело было в нем, тогда характер искажений был бы другим).
Go to the top of the page
 
+Quote Post
Spider
сообщение Aug 7 2008, 13:14
Сообщение #23


В поисках истины
***

Группа: Свой
Сообщений: 431
Регистрация: 7-01-06
Из: Россия
Пользователь №: 12 923



Цитата(defunct @ Aug 7 2008, 19:53) *
Проблема с данными, кстати, если читать одну и ту же строку несколько раз подряд проблема исчезает? или после изменения ячейки, постоянно читается неверное значение?
Ничего подобного. Я писал тест памяти, который пишет в память 0xFF 0xAA 0x00 0x55 и потом это от туда читает 10 раз. Так же ещё ряд тестов, и всё ровно. Только что пробовал это на разных задержках.
Цитата(defunct @ Aug 7 2008, 19:53) *
Теоретически для тактирования 8Mhz и 70ns памяти, задержки могуть быть нулевые, но тут может влиять разводка (паразитные емкости растягивают фронты). Поэтому для теста установить макс задержку и посмотреть осциилографом форму сигналов на линиях данных. Еще, если сигнальные линии подключены к шине через резисторы - последние убрать или заменить на нулевки.
Память чтоит максимально близко к процу, никаких резисторов на шинах нет.
Цитата(defunct @ Aug 7 2008, 19:53) *
Пардон пропустил мимо ушей что модем GSM, тогда он фонит еще серьезнее. Однозначно ШД забивается помехами - попробуйте разместить модем как можно дальше от устройства. Поставить экраны (напр для теста обмотать девайс паралоном, а сверху фольгой). Если подтвердится, боюсь придется переделывать разводку полностью. Также проверьте не затягивается ли фронт сигнала "R" (хотя если бы дело было в нем, тогда характер искажений был бы другим).

Тяжко, но попробую. Кстати такое не наблюдалось ранее, прошивку пишу не первый день smile.gif
Go to the top of the page
 
+Quote Post
rezident
сообщение Aug 7 2008, 13:39
Сообщение #24


Гуру
******

Группа: Свой
Сообщений: 10 920
Регистрация: 5-04-05
Пользователь №: 3 882



Цитата(Alexey Belyaev @ Aug 7 2008, 19:14) *
Ничего подобного. Я писал тест памяти, который пишет в память 0xFF 0xAA 0x00 0x55 и потом это от туда читает 10 раз. Так же ещё ряд тестов, и всё ровно. Только что
Любопытно. Эта длинная тирада означает ответ "нет, не исчезает" или "да, читается неверное значение"? cranky.gif Вопрос был
Цитата
если читать одну и ту же строку несколько раз подряд проблема исчезает? или после изменения ячейки, постоянно читается неверное значение?

Только в русском языке фраза может содержать одновременно и положительный и отрицательный ответ laughing.gif
Go to the top of the page
 
+Quote Post
Spider
сообщение Aug 8 2008, 05:41
Сообщение #25


В поисках истины
***

Группа: Свой
Сообщений: 431
Регистрация: 7-01-06
Из: Россия
Пользователь №: 12 923



Ну в общем ситуация такая. Была просадка напряжения sad.gif Когда модем начинал что-то натужно передавать он цуть цуть просаживал напряжение (несмотря на кучу кондёров танталовых и прочего). Этой просадки хватало чтобы память дурила. И так интересно, выбивала всего то по 1 биту sad.gif
Go to the top of the page
 
+Quote Post

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

 


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


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