Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > C/C++: Общие вопросы > Локальная переменная меняет знач. "сама"


Автор: DanilSoldatov 12.8.2008, 09:26
Здравствуйте!
Пишу прогу на Си и иногда встречаюсь с такой ситуацией, что
локальная переменная меняет свое значение "сама по себе". Ну т.е. явно я ей ничего не присваиваю, а значение "чудесным образом" меняется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);
}

Автор: Daevaorn 12.8.2008, 09:32
Ужасный код.  Куча магических чисел и разный стиль именования идентификаторов.

А то что переменная вдруг меняет своё значения - виноват автор кода. Он явно так сильно "химичит" с памятью, что просто выходит за границы массива где-то и портит стек.

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

Автор: DanilSoldatov 12.8.2008, 10:25
Что касается типов:

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 и размеру этой строки.

Что не так?

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

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

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

а вот это уже тебе нужно узнать что не так smile
Я лишь выдвинул предположение.
Не факт, что это строка имеет длину > 11.

Автор: xvr 12.8.2008, 14:03
Код

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 

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

А вот єто уже по сути, 
спасибо,  я уже нашел

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

Автор: Supersedes 13.8.2008, 08:18
Цитата

Вот фрагмент Си-шного кода, где переменная 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-й строке она тоже сама себя прописала!?

Автор: ksili 13.8.2008, 08:56
Supersedes, ты комментарии-то в коде читал?

Автор: MastEdm 13.8.2008, 21:41
Лучше, конечно, код переписать. А если лениво, то в дебагере делай breakpoint на 8 строчку, а потом watch на память, выделенную под delta. Как только её кто-то поменяет, дебагер тебе об этом сообщит.

Автор: Supersedes 14.8.2008, 14:21
ksili, нет. Щаз прочитаю..

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)