Форум: "Потрепаться";
Текущий архив: 2003.11.24;
Скачать: [xml.tar.bz2];
ВнизИнтересно работает оптимизатор... Найти похожие ветки
← →
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;
Скачать: [xml.tar.bz2];
Память: 0.48 MB
Время: 0.011 c