nixp.ru v3.0

17 января 2017,
вторник,
07:43:42 MSK

DevOps с компанией «Флант»
DanilSoldatov написал 12 августа 2008 года в 10:40 (470 просмотров) Ведет себя неопределенно; открыл 3 темы в форуме, оставил 4 комментария на сайте.

Здравствуйте!

Пишу прогу на Си и иногда встречаюсь с такой ситуацией, что

локальная переменная меняет свое значение «сама по себе». Ну т.е. явно я ей ничего не присваиваю, а значение «чудесным образом» меняется:). Я так понимаю, что в эту область памяти записывается какое-то другое значение, но почему? Есть ли какой-нить более-менее универсальный способ следить и отлавливать такие ошибки? Заранее спасибо.

Вот фрагмент Си-шного кода, где переменная 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 байтов — дату и время, хотя это неважно:)):

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);

}

myst

Скомпилируй без оптимизации, пройдись GDB по коду и найди строку на которой это происходит. И никогда, запомни, никогда не пользуйся camelCase.

rgo


char arr[1], year[3];
      memset(arr, 0, 2); /* Переполнение буфера номер раз*/
      memset(year, 0, 4); /* переполнение буфера номер два */
...
      year[3]=aData[aFromPos + 1]; /* три */
...
      arr[1]=aData[aFromPos + 3]; /* четыре */
/* дальше ещё несколько того же типа... */

Правда я не думаю, что переполнение на один байт может достать до дельты. Даже если -fomit-frame-pointer указано. В лучшем случае из-за этого можно получить какой-нибудь SEGFAULT при возврате из функции.

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

ecobeingecobeing.ru
Экология и вегетарианство на благо всем живым существам Планеты.