Модераторы: Daevaorn
  

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Локальная переменная меняет знач. "сама", Локальная переменная меняет знач. "сама" 
:(
    Опции темы
DanilSoldatov
Дата 12.8.2008, 09:26 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 9
Регистрация: 30.4.2008

Репутация: нет
Всего: нет



Здравствуйте!
Пишу прогу на Си и иногда встречаюсь с такой ситуацией, что
локальная переменная меняет свое значение "сама по себе". Ну т.е. явно я ей ничего не присваиваю, а значение "чудесным образом" меняетсяsmile. Я так понимаю, что в эту область памяти записывается какое-то другое значение, но почему? Есть ли какой-нить более-менее универсальный способ следить и отлавливать такие ошибки? Заранее спасибо.

Вот фрагмент Си-шного кода, где переменная delta неожиданно меняет свое значение:
Код

      
            int len= 0, I = 0, delta = 0;
  
            while (len < length - 11 - 4*I)
            {
                delta = 17 + len + 4*I;
                vCodeman.ServiceType_id = WordFromArray(vResultBuf, delta - 2);
                vCodeman.Datalen = StrFromArray(vResultBuf, delta, vCodeman.ManualData);
    
                //вот тут значение delta одно
                                DateTimeFromArray(vResultBuf, delta + vCodeman.Datalen + 2, &vCodeman.UpdateDate);
                        //а тут уже другое значение delta 

                CodemanToFlash( &vCodeman );
                memset( &vCodeman, 0, sizeof(struct CodemanData));
                len += WordFromArray(vResultBuf, delta - 4);
                I++;    
            }


Код ф-ции DateTimeFromArray следующий(эта ф-ция берет из байтовой послед-ти 12 байтов - дату и время, хотя это неважноsmile):

Код

void DateTimeFromArray(const char *aData, const int aFromPos, DateTime *vDateTime)
{
    char arr[1], year[3];
  
    memset(arr, 0, 2);
    memset(year, 0, 4);
  
    year[0]=50; 
    year[1]=48;    
    year[2]=aData[aFromPos]; 
    year[3]=aData[aFromPos + 1];  
    vDateTime->dt.TM_YEAR   = atoi(year);
  
    arr[0]=aData[aFromPos + 2];
    arr[1]=aData[aFromPos + 3]; 
    vDateTime->dt.TM_MONTH  = atoi(arr);
  
    arr[0]=aData[aFromPos + 4];
    arr[1]=aData[aFromPos + 5];   
    vDateTime->dt.TM_DAY    = atoi(arr);
  
    arr[0]=aData[aFromPos + 6];
    arr[1]=aData[aFromPos + 7]; 
    vDateTime->tt.TM_HOUR   = atoi(arr);
  
    arr[0]=aData[aFromPos + 8];
    arr[1]=aData[aFromPos + 9]; 
    vDateTime->tt.TM_MINUTE = atoi(arr);
  
    arr[0]=aData[aFromPos + 10];
    arr[1]=aData[aFromPos + 11]; 
    vDateTime->tt.TM_SECOND = atoi(arr);
}

PM MAIL   Вверх
Daevaorn
Дата 12.8.2008, 09:32 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 2155
Регистрация: 29.11.2004
Где: Москва

Репутация: 51
Всего: 70



Ужасный код.  Куча магических чисел и разный стиль именования идентификаторов.

А то что переменная вдруг меняет своё значения - виноват автор кода. Он явно так сильно "химичит" с памятью, что просто выходит за границы массива где-то и портит стек.
PM MAIL WWW   Вверх
Torsten
Дата 12.8.2008, 09:33 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 174
Регистрация: 10.6.2008
Где: Pskov

Репутация: 3
Всего: 7



DanilSoldatov, 
пустой код, потому что о типах ни слова и их размеров и много магических чисел.
Вообще у меня была такая байда из-за компилятора старого и буста, но это С++. 
У тебя же судя по всему при работе с массивом проблемы.
Если ты точно локализовал функцию, в которой значение меняется, сделай трассировку, чтобы определить строку, в которой происходит изменение.
Для начала советую присмотрется к aData и размеру этой строки.

Это сообщение отредактировал(а) Torsten - 12.8.2008, 09:35
--------------------
We have no begining, we have no end. We are infinite.
PM MAIL   Вверх
DanilSoldatov
Дата 12.8.2008, 10:25 (ссылка) |  (голосов:1) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 9
Регистрация: 30.4.2008

Репутация: нет
Всего: нет



Что касается типов:

struct CodemanData vCodeman;
char vResultBuf[CODEMAN_MAX_SIZE] = {0};

Цитата(Torsten @  12.8.2008,  09:33 Найти цитируемый пост)
Если ты точно локализовал функцию, в которой значение меняется, сделай трассировку, чтобы определить строку, в которой происходит изменение.

Я так понимаю, что в ф-ции DateTimeFromArray что-то не так т.к. после нее переменная delta меняет свое значение (хотя в DateTimeFromArray она как константа)

Цитата(Torsten @  12.8.2008,  09:33 Найти цитируемый пост)
Для начала советую присмотрется к aData и размеру этой строки.

Что не так?

PM MAIL   Вверх
Torsten
Дата 12.8.2008, 11:21 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 174
Регистрация: 10.6.2008
Где: Pskov

Репутация: 3
Всего: 7



Цитата(DanilSoldatov @  12.8.2008,  10:25 Найти цитируемый пост)
хотя в DateTimeFromArray она как константа)

Даже более, она передается по значению и копируется. Это не ссылка и не указатель.

Цитата(DanilSoldatov @  12.8.2008,  10:25 Найти цитируемый пост)
Что не так?

а вот это уже тебе нужно узнать что не так smile
Я лишь выдвинул предположение.
Не факт, что это строка имеет длину > 11.
--------------------
We have no begining, we have no end. We are infinite.
PM MAIL   Вверх
xvr
Дата 12.8.2008, 14:03 (ссылка) |    (голосов:2) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 7046
Регистрация: 28.8.2007
Где: Дублин, Ирландия

Репутация: 60
Всего: 223



Код

void DateTimeFromArray(const char *aData, const int aFromPos, DateTime *vDateTime)
{
    char arr[1], year[3];
  
    memset(arr, 0, 2);
    memset(year, 0, 4);
Массивы arr и year описанны как массивы из 1го и 3х байтов, memset'ы затирают по 1му байту за границами обоих массивов, удивительно, что из DateTimeFromArray вообще вернулись  smile 
PM MAIL   Вверх
DanilSoldatov
Дата 12.8.2008, 14:33 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 9
Регистрация: 30.4.2008

Репутация: нет
Всего: нет



Цитата(xvr @  12.8.2008,  14:03 Найти цитируемый пост)
Массивы arr и year описанны как массивы из 1го и 3х байтов, memset'ы затирают по 1му байту за границами обоих массивов, удивительно, что из DateTimeFromArray вообще вернулись  smile  

А вот єто уже по сути, 
спасибо,  я уже нашел
PM MAIL   Вверх
ksili
Дата 12.8.2008, 15:07 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 2069
Регистрация: 3.11.2005
Где: Красноярск

Репутация: 1
Всего: 17



vResultBuf это получается char*. А память под массив на который он указывает, нигде не выделяется


--------------------
Ничто так не развивает аналитическое мышление, как отладка сложной программы без возможности пошагового выполнения (с)
PM MAIL   Вверх
Supersedes
Дата 13.8.2008, 08:18 (ссылка)    | (голосов:2) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 36
Регистрация: 29.7.2008

Репутация: нет
Всего: нет



Цитата

Вот фрагмент Си-шного кода, где переменная delta неожиданно меняет свое значение: 
Код

            int len= 0, I = 0, delta = 0;
  
            while (len < length - 11 - 4*I)
            {
                delta = 17 + len + 4*I;
                vCodeman.ServiceType_id = WordFromArray(vResultBuf, delta - 2);
                vCodeman.Datalen = StrFromArray(vResultBuf, delta, vCodeman.ManualData);
    
                //вот тут значение delta одно
                                DateTimeFromArray(vResultBuf, delta + vCodeman.Datalen + 2, &vCodeman.UpdateDate);
                        //а тут уже другое значение delta 

                CodemanToFlash( &vCodeman );
                memset( &vCodeman, 0, sizeof(struct CodemanData));
                len += WordFromArray(vResultBuf, delta - 4);
                I++;    
            }


В 5-й строке она тоже сама себя прописала!?

Это сообщение отредактировал(а) Supersedes - 13.8.2008, 08:19
PM MAIL ICQ   Вверх
ksili
Дата 13.8.2008, 08:56 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 2069
Регистрация: 3.11.2005
Где: Красноярск

Репутация: 1
Всего: 17



Supersedes, ты комментарии-то в коде читал?


--------------------
Ничто так не развивает аналитическое мышление, как отладка сложной программы без возможности пошагового выполнения (с)
PM MAIL   Вверх
MastEdm
Дата 13.8.2008, 21:41 (ссылка) |   (голосов:1) Загрузка ... Загрузка ... Быстрая цитата Цитата


Master
*


Профиль
Группа: Участник
Сообщений: 178
Регистрация: 3.12.2005
Где: Москва, МГИУ

Репутация: 1
Всего: 2



Лучше, конечно, код переписать. А если лениво, то в дебагере делай breakpoint на 8 строчку, а потом watch на память, выделенную под delta. Как только её кто-то поменяет, дебагер тебе об этом сообщит.
PM MAIL   Вверх
Supersedes
Дата 14.8.2008, 14:21 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 36
Регистрация: 29.7.2008

Репутация: нет
Всего: нет



ksili, нет. Щаз прочитаю..
PM MAIL ICQ   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
Правила форума "С++:Общие вопросы"
Earnest Daevaorn

Добро пожаловать!

  • Черновик стандарта C++ (за октябрь 2005) можно скачать с этого сайта. Прямая ссылка на файл черновика(4.4мб).
  • Черновик стандарта C (за сентябрь 2005) можно скачать с этого сайта. Прямая ссылка на файл черновика (3.4мб).
  • Прежде чем задать вопрос, прочтите это и/или это!
  • Здесь хранится весь мировой запас ссылок на документы, связанные с C++ :)
  • Не брезгуйте пользоваться тегами [code=cpp][/code].
  • Пожалуйста, не просите написать за вас программы в этом разделе - для этого существует "Центр Помощи".
  • C++ FAQ

Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, Earnest Daevaorn

 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | C/C++: Общие вопросы | Следующая тема »


 




[ Время генерации скрипта: 0.0517 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.