Top.Mail.Ru
Мастера DELPHI, Delphi programming community Титульная страница Поиск, карта сайта Написать письмо 
| Новости | Поиск | FAQ | Статьи | Книги | Новости VCL |
| Форумы ЧАТ | Орешник | KOL и MCK |
Форумы -» Основная («Начинающим»)/ Базы / WinAPI / Компоненты / Сети / Media / Игры / Corba и COM / KOL / FreePascal / .Net / Прочее / RSDN.ORG

« предыдущая ветвь | форум | следующая ветвь »

Range Check Error [D5, Win95/98]


MegaVolt ©   (2006-03-30 18:02:00) 

Почему в первой функции при включенной проверке выхода за границы диапазонов вылазит ошибка а во второй нет

function F1(s:string):cardinal;
begin
 Result:=(StrToInt(s) and $FF) shl 24;
end;

function F2(s:string):cardinal;
begin
 Result:=(StrToInt(s) shl 24) and $FF000000;
end;

procedure TForm1.Button1Click(Sender: TObject);
begin
 ShowMessage(IntToStr(F1('192')));
end;

procedure TForm1.Button2Click(Sender: TObject);
begin
 ShowMessage(IntToStr(F2('192')));
end;


причём если сдвиг делать на меньшее число байт то всё нормально.


Rouse_   (2006-03-31 11:15:00) [1]

Ну в принципе да...


MegaVolt   (2006-03-31 11:12:00) [2]

ИМХО ничего там не вычитается :) Просто если смотреть на первый бит как на знаковый то число отрицательное. А если считать число положительным то это и есть положительное число :)


Rouse_   (2006-03-31 10:38:00) [3]

Ну и в конце концов - если отключена данная проверка, то ты всеравно получишь результат: просто отрицательное значение вычтеца из 4294967295
и получиться число которое соответствует типу Cardinal


Rouse_   (2006-03-31 10:35:00) [4]

За переполнение отвечает флаг OF. по нему тоже идет проверка...
А почему не учитывается - ну ты нашел у кого спросить :)
Спрашивай у разработчиков компилятора :)


MegaVolt   (2006-03-31 10:29:00) [5]

>Вот эти две инструкции проверяют - не является ли полученное число отрицательным, и если оно является таковым - то выполняется BoundErr.

А почему не учитывается что наше число впринципе не может быть отрицатеьным. Т.к. cardinal только положителен.

И почему во втором случае корый действительно при сдвиге неизвесно какого числа может привести к переполнению компилятор молчит? Т.е. сдвиг числа большего чем 255 привелёт к переполнению.


Rouse_   (2006-03-31 10:14:00) [6]


> И зачем нужен RangeCheck, если я знаю, что мне нужно, а
> компилятор лишь думает, что я этого не знаю. Проще ставить
> {$R+} там где есть какая-то неуверенность в коде.

Вот такой код при отключенной проверке выхода за пределы диапазона приведет к AV, т.к. цикл будет крутиться от нуля до 4294967295
var
 I: Cardinal;
begin
 List.Count := 0;
 I := 0 to List.Count - 1 do
 begin
    ListItems[I] := 'qwe';  
 end;
end;


Rouse_   (2006-03-31 10:00:00) [7]

Тут все очень просто:
Cardinal является у нас unsigned 32-bit, диапазон 0..4294967295
При выполнении данного кода генерируются такие инструкции:

mov eax,[ebp-$04]
call StrToInt
mov ebx,eax
and ebx,$000000ff
shl ebx,$18
test ebx,ebx
jns $0049cd2a
call @BoundErr


Вот эти две инструкции
test ebx,ebx
jns $0049cd2a

проверяют - не является ли полученное число отрицательным, и если оно является таковым - то выполняется BoundErr.

Признак отрицательного значения у нас находиться в флаге SF, который после выполнения инструкции shl ebx,$18 становиться равным единице.

Результат выполнения данной функции равен: -1073741824

Измени обьявление функции на такое: function F1(s:string):Integer;
и ошибка исчезнет :)


Defunct   (2006-03-31 04:28:00) [8]

Конкретно в таких случаях я поступаю так:
{$R-}
Хотя чаще просто выключаю Range Checking вообще в опциях проекта.

И зачем нужен RangeCheck, если я знаю, что мне нужно, а компилятор лишь думает, что я этого не знаю. Проще ставить {$R+} там где есть какая-то неуверенность в коде.


Германн   (2006-03-31 01:11:00) [9]


> Pavia ©   (30.03.06 22:25) [2]
>
> Во второй функции дельфи подставляет
> StrToInt(s:string):int64;
> А в первой
> StrToInt(s:string):integer;
> Так что, во второй запас большой.


Есть StrToInt, а есть StrToInt64. Это две большие разницы. И дельфи врядли сможет сама "подставить" вместо одной другую. Да и не в этой функции дело.
Мне непонятен сам смысл сабжа, в котором присутствует функция and, которая может только уменьшить результат, а никак не увеличить.


Pavia   (2006-03-30 22:25:00) [10]

Во второй функции дельфи подставляет
StrToInt(s:string):int64;
А в первой
StrToInt(s:string):integer;
Так что, во второй запас большой.


MegaVolt   (2006-03-30 18:06:00) [11]

Причём если передать число большее чем байт вторая функция всё равно не ругается хотя за границу cardinal вылам точно.


Наверх

Титульная страница Поиск, карта сайта Написать письмо