![]() |
|
|
|||||||
| Регистрация | << Правила форума >> | FAQ | Пользователи | Календарь | Поиск | Сообщения за сегодня | Все разделы прочитаны |
![]() |
|
|
Опции темы | Поиск в этой теме | Опции просмотра |
|
#1
|
|||
|
|||
|
Добрый день!
Использую в работе Delphi XE, всё хорошо и вот недавно возникла проблема перестали работать некоторые циклы. Проект большой, суть его в том имеется таблица значений, столбцов порядка 30, а строк может быть много, от единиц до десятков и сотен тысяч. Строки обрабатываются в циклах и вот некоторые из этих циклов, при количестве итераций больше 32597 строк, перестали работать, то есть программа их просто проскакивает, при этом никаких условий перед циклом нет. Так-же заметил что в некоторых случаях такое возникало когда цикл был не от 0, но тем не менее первое значение цикла было меньше конечного: Код:
procedure SomeProc(FirstRow, LastRow: integer);{FirstRow заведомо меньше LastRow}
var
i: integer;
begin
{Некоторые начальные операции, которых может и не быть}
for i := FirstRow to LastRow do
begin
{операции со строкой i}
end;
end;Временное решение было таким: Код:
procedure SomeProc(FirstRow, LastRow: integer);{FirstRow заведомо меньше LastRow}
var
i, j: integer;
begin
{Некоторые начальные операции, которых может и не быть}
for j := 0 to (LastRow - FirstRow) do
begin
i := FirstRow + j;
{операции со строкой i}
end;
end;В итоге цикл работает при количестве итерации большем 32597. Но был и случай когда цикл уже был от 0: Код:
procedure SomeProc;{FirstRow заведомо меньше LastRow}
var
i: integer;
begin
{Некоторые начальные операции, которых может и не быть}
for i := 0 to RowCount - 1 do
begin
{операции со строкой i}
end;
end;В этом случае, сделал так: Код:
procedure SomeProc;{FirstRow заведомо меньше LastRow}
var
i, j: integer;
begin
{Некоторые начальные операции, которых может и не быть}
for j := 0 to RowCount - 1 do
begin
i := j;
{операции со строкой i}
end;
end;И цикл начал работать. При замене цикла на цикл while всё работает. Оптимизация отключена глобально. В чём тут может быть проблема? |
|
#2
|
|||
|
|||
|
Проблема в Delphi XE - все творения Embarcadero заметно проигрывают более ранним версиям в стабильности и скорости. Почему в такой ситуации Embarcadero продолжает накручивать разные плюшки (вообщем-то интересные, но не ценой же стабильности) и выпускать все новые и новые версии, а не отлавливает баги уже существующих версий - вопрос к ним (наверное это торжество маркетинга над программингом
). Но то что RAD Studio со сложными проектами превращается в глюкозавра - печальный факт. Решение - или подстраиваться под баги (что вы и продемонстрировали) или уйти на стабильную версию (а вы думаете почему в сети до сих пор бродит так много сборок Delphi 7, а кое-где до сих пор продается в качестве отдельного продукта; лицензия на Delphi 7 дается вместе с RAD Studio?)Последний раз редактировалось Lucky192, 10.10.2011 в 16:06. |
|
#3
|
|||
|
|||
|
Воспроизвел ошибку на тестовом проекте, вынес в класс:
Код:
TError = class
private
function Add(FromV, ToV: Integer): Integer;
function Check(Row: Integer; Val: Byte): Boolean;
function Operation(Index: Integer; Func: TFunc<Integer,Integer>): Integer;
public
function Run(Count: Integer): Integer;
end;
function TError.Add(FromV, ToV: Integer): Integer;
var
i: Integer;
res: Integer;
func: TFunc<Integer,Integer>;
begin
res := 0;
func :=
function(data: Integer): Integer
begin
if Check(i, MAXBYTE div 2) then
Result := data;
end;
for i := FromV to ToV do
res := Operation(i, func);
Result := res;
end;
function TError.Check(Row: Integer; Val: Byte): Boolean;
begin
Result := True;
end;
function TError.Operation(Index: Integer; Func: TFunc<Integer, Integer>): Integer;
begin
if Assigned(Func) then
Result := Func(Index);
end;
function TError.Run(Count: Integer): Integer;
begin
Result := Add(0, Count);
end;В результате получаем, если:
Если реализацию анонимного метода вынести в отдельный метод, тогда всё работает как надо. Если условие Check сделать без параметров, тогда будет всё работать и с анонимным методом. Либо я что-то делаю не так, либо это баг в Delphi XE, если это так, то стоит ли отправлять это на сайт Эмбаркадеро? |
|
#4
|
||||
|
||||
|
Вообще меня смущает ваша цифра 32767. Складывается впечатление, что по неведомым причинам у вас в цикле используется 2 байтный счетчик, а не 4 байтный. А что если счетчик определить не как Integer, а как DWord?
|
|
#5
|
|||
|
|||
|
Тут именно баг компилятора, вот такой код он генерирует для цикла:
Код:
0040F8D0 FF400C inc dword ptr [eax+$0c]
Test.dpr.32: for i := FromV to ToV do
0040F8D3 8B45E0 mov eax,[ebp-$20]
0040F8D6 8B400C mov eax,[eax+$0c]
0040F8D9 663B45E6 cmp ax,[ebp-$1a]
0040F8DD 7ED7 jle $0040f8b6 {переход на тело}и тут действительно счётчик 16 битный. Готовлю отчет в QualityCentral. |
|
#6
|
|||
|
|||
|
Запостил отчёт:
http://qc.embarcadero.com/wc/qcmain.aspx?d=99909 Проголосуйте, если есть возможность. |