Главная страница
Top.Mail.Ru    Яндекс.Метрика
Текущий архив: 2003.11.24;
Скачать: CL | DM;

Вниз

Интересно работает оптимизатор...   Найти похожие ветки 

 
Delirium ©   (2003-10-30 11:07) [0]

{$O-} или {$O+}
procedure TForm1.Button1Click(Sender: TObject);
var
i:Integer;
arr:Array[1..3] of Real;
s:Real;
begin
s:=10;
i:=4;
arr[i]:=50;
ShowMessage(FloatToStr(s));
end;

Как показал эксперимент s=10 при {$O-} и s=50 при {$O+}, но!,
ошибка "out of bounds" не появляется ни в одном случае, как сие оценить?


 
Skier ©   (2003-10-30 11:09) [1]

{$R+} ?


 
Delirium ©   (2003-10-30 11:13) [2]

Опа, а про то, что {$R} по умолчанию "-", я и не подумал...
Ну ладно, а как быть с оптимизатором, откуда разные значения?


 
Skier ©   (2003-10-30 11:17) [3]


> Ну ладно, а как быть с оптимизатором, откуда разные значения?

Х.З. :)


 
cyborg ©   (2003-10-30 12:57) [4]

Выравнивание видимо, либо переменные в регистрах, старая в регистре, а присваиваешь в память.


 
Anatoly Podgoretsky ©   (2003-10-30 13:01) [5]

Delirium © (30.10.03 11:13) [2]
Одну операцию он выпольнил в регистрах и не испортил памяти, а другую наоборот.
Говорить о каких то рузульратах при неправильной программе грешно. Если отключена авторопверка диаапазовнов, то ее надо проводить вручную. А различие именно в регистровых операциях.


 
icWasya ©   (2003-10-30 14:19) [6]

короче, у меня получилось, что
при {$O+}
адреса переменных выглядят так
arr[1] [ebp-$2c]
arr[2] [ebp-$24]
arr[3] [ebp-$1c]
несуществующий arr[4] [ebp-$14]
s [ebp-$04]

то есть массив занимает не 24, а 32 байта; s и arr[4] занимают разные ячейки памяти , и соответственно в конце S =10

при {$O-}
адреса переменных выглядят так
arr[1] [ebp-$2c]
arr[2] [ebp-$24]
arr[3] [ebp-$1c]
несуществующий arr[4] [ebp-$14]
s [ebp-$14]

то есть массив занимает 24 байта; s и arr[4] занимают одну и ту же ячейку памяти , и соответственно в конце S =50


 
Ketmar ©   (2003-10-30 15:47) [7]

ну дык оптимизатор -- он на то и оптимизатор. наивно ожидать соответствие "один к одному" в оптимизированной программе.
а, кстати, статическую проверку диапазонов могли бы делать всегда. ведь несложно, а приятно. а то ведь $R, гад, он ещё и на присвоения влияет. типа:
var
a: SmallInt;
b: Integer;

b := -123456789;
a := b;

при R+ радостно грохнется. не уверен, что это логичное поведение. имхо, было бы удобней считать это переполнением, а не нарушением диапазона.


 
Anatoly Podgoretsky ©   (2003-10-30 16:13) [8]

Ketmar © (30.10.03 15:47) [7]
Это логичное поведение или ты берешь правильность на себя или ты позволяешь это сделать компилятору, ну это разница логически-филосовская, но это больше нарушения диапазона, b в a не помещается, а вот такая операция a:=a+1 вот здесь уже переполнение.


 
Ketmar ©   (2003-10-30 16:31) [9]

но, имхо, было бы удобнее, чтобы существовал отдельный ключик только для массивов. а то задалбываюсь явные приведения типов по программе раскидывать. или, если уж компилятор такой принципиальный, чтобы в режиме R+ выдавал варнинг "неявное приведение типов, аднака".


 
Anatoly Podgoretsky ©   (2003-10-30 16:32) [10]

Ну он исправится


 
han_malign ©   (2003-10-30 16:41) [11]

А вам не кажется, что, уважающий себя, оптимизатор выкинет строчку arr[i]:=50;(да и arr:Array[1..3] of Real; - туда же), т.к. это значение нигде не используется(уж Hint-ы выдаст точно).

> не 24, а 32 байта
- помоему - бред, даже в VC, максимальное выравнивание данных - на границу 8 байт, на параграф только код равняется. Разве, что для гипотетического использования MMX, который в Delphi не поддерживается, и к тому же целочисленный... Не знаю, может в FPU есть команда со счетверенным 256-битным операндом...


 
Ketmar ©   (2003-10-30 16:59) [12]

ну да, кстати. по идее весь код до ShowMeswsage (вместе с переменными) должен быть выкинут, а FloatToStr преобразован в вызов функции с параметром-константой. как поведёт себя дельфи, мне проверять лень %-)
и вообще, мы тут про $R+ говорим, при чём тут какие-то оптимизаторы?! %-)


 
Delirium ©   (2003-10-30 17:49) [13]

> "по идее весь код до ShowMeswsage (вместе с переменными) должен быть выкинут"

Это с чего?

begin
s:=10; // s используется в FloatToStr
i:=4; // i исползуется в arr[i]
arr[i]:=50; // собственно arr[i] нигде не используется,
// но такие операции вообще не выбрасываются компилятором,
// даже если было бы напиано arr[1]:=50; - мало-ли что
// я модифицирую через этот массив?
ShowMessage(FloatToStr(s));
end;


 
han_malign ©   (2003-10-30 17:59) [14]

Ничего он не выкидывает:
{$O+}
add esp,-$20
s:=10;
xor eax,eax
mov [esp],eax
mov [esp+$04],$40240000
i:=4;
mov eax,4
arr[i]:=50;
xor edx,edx
mov [esp+eax*8],edx //esp+$20
mov [esp+eax*8+$04],$40490000 //esp+$24

{$O-}
push ebp
mov ebp,esp
add esp,-$30 //esp
mov [ebp-$14],edx //esp+$1c
mov [ebp-$04],eax //esp+$2c
s:=10;
xor eax,eax
mov [ebp-$10],eax //esp+$20
mov [ebp-$0c],$40240000 //esp+$24
i:=4;
mov [ebp-$08],4 //esp+$28
arr[i]:=50;
mov eax,[ebp-$08]
xor edx,edx
mov [ebp+eax*8-$38],edx //ebp-$18 //esp+$18
mov [ebp+eax*8-$34],$40490000 //ebp-$14 //esp+$1c

- только никак не врублюсь, где и в какую сторону стек засирается... - домой пожалуй пора двигать.

В первом случае, явно адрес возврата обнуляется, и все это падает...

Тестовая програмка: program opt;
{$APPTYPE CONSOLE}
uses Windows;
{$O+}
var a: extended;
type tt=class
public
procedure Test(Sender: pointer);
end;
procedure tt.Test(Sender: pointer);
var
i:Integer;
arr:Array[1..3] of Real;
s:Real;
begin
s:=10;
i:=4;
arr[i]:=50;
Writeln(s);
end;
var t: tt;
begin
t:=tt.Create;
t.Test(nil);
t.Free;
end.


 
Ketmar ©   (2003-10-30 18:25) [15]

>Delirium
а это из Data Flow Analysis следует. по исходнику ЯСНО, что: arr -- локальна, и ни разу нигде не используется. следовательно, i -- тоже не используется (потому что arr уже выкинули на предыдущем шаге). значение a известно на стадии компиляции, и потому смело может быть заменено на константу (не забываем, все переменные -- локальные, модификаторы absolute отсутствуют). предлагаю по этому поводу почитать "дракона" %-)
а то, что оптимизатор в дельфи далеко не лучший, это, кажется, общеизвестный факт. зато быстрый. это тоже факт.



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

Текущий архив: 2003.11.24;
Скачать: CL | DM;

Наверх




Память: 0.51 MB
Время: 0.027 c
3-78754
Vemer
2003-11-03 12:58
2003.11.24
Sweep БД из-под Delphi.


14-79115
Knight
2003-10-30 00:32
2003.11.24
Локальный сервер под Линух...


3-78784
Islander
2003-11-05 15:25
2003.11.24
Как проверить данные перед посылкой в БД, работая через ADO


3-78749
Dysan
2003-11-06 11:00
2003.11.24
Как через ADOQuery сделать выборку из таблиц из разных директори?


1-78907
Unknown
2003-11-12 12:09
2003.11.24
Dll