Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "Основная";
Текущий архив: 2006.05.07;
Скачать: [xml.tar.bz2];

Вниз

Range Check Error   Найти похожие ветки 

 
MegaVolt ©   (2006-03-30 18:02) [0]

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

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;


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


 
MegaVolt ©   (2006-03-30 18:06) [1]

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


 
Pavia ©   (2006-03-30 22:25) [2]

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


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


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


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


 
Defunct ©   (2006-03-31 04:28) [4]

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

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


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

Тут все очень просто:
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;
и ошибка исчезнет :)


 
Rouse_ ©   (2006-03-31 10:14) [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;


 
MegaVolt ©   (2006-03-31 10:29) [7]

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

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

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


 
Rouse_ ©   (2006-03-31 10:35) [8]

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


 
Rouse_ ©   (2006-03-31 10:38) [9]

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


 
MegaVolt ©   (2006-03-31 11:12) [10]

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


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

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



Страницы: 1 вся ветка

Форум: "Основная";
Текущий архив: 2006.05.07;
Скачать: [xml.tar.bz2];

Наверх




Память: 0.47 MB
Время: 0.009 c
15-1145095256
SergP.
2006-04-15 14:00
2006.05.07
Нужна помощь по скачиванию файла


15-1145187539
Константин Артемьев
2006-04-16 15:38
2006.05.07
Заказ на небольшую Delphi программу


3-1141557640
maximsms
2006-03-05 14:20
2006.05.07
Firebird 1.5. error -901, "feature is not supported"


15-1144909345
DelphiN!
2006-04-13 10:22
2006.05.07
IntToStr в C#


15-1144914947
Kolan
2006-04-13 11:55
2006.05.07
Как принудитеьно запустить скан диск.





Afrikaans Albanian Arabic Armenian Azerbaijani Basque Belarusian Bulgarian Catalan Chinese (Simplified) Chinese (Traditional) Croatian Czech Danish Dutch English Estonian Filipino Finnish French
Galician Georgian German Greek Haitian Creole Hebrew Hindi Hungarian Icelandic Indonesian Irish Italian Japanese Korean Latvian Lithuanian Macedonian Malay Maltese Norwegian
Persian Polish Portuguese Romanian Russian Serbian Slovak Slovenian Spanish Swahili Swedish Thai Turkish Ukrainian Urdu Vietnamese Welsh Yiddish Bengali Bosnian
Cebuano Esperanto Gujarati Hausa Hmong Igbo Javanese Kannada Khmer Lao Latin Maori Marathi Mongolian Nepali Punjabi Somali Tamil Telugu Yoruba
Zulu
Английский Французский Немецкий Итальянский Португальский Русский Испанский