Форум: "Прочее";
Текущий архив: 2013.03.22;
Скачать: [xml.tar.bz2];
ВнизОшибка Access violation... и странный указатель Найти похожие ветки
← →
ПЛОВ © (2012-07-12 15:26) [0]Народ, подскажите, куда копать для поиска причин таких ошибок?
Есть обычный односвязный динамический список указателей, состоящий из элементов типа
PDataListItem = ^TDataListItem;
TDataListItem = record
Data: Pointer; // Data
NextItem: PDataListItem; // Next item
end;
и оформленный в виде класса. Был тестен-перетестен.
Сейчас юзаю его в программе, выбирают из БД записи, загоняю их в список (в виде объектов), после чего данные из этого списка добавляются в ListView.
Все записи в ListView попадают, ошибок нет.
Но! При обновлении списка (опять загрузка из БД - список - ListView) вылетает ахис виолейшен. Конкретно - в процедуре очистки списка, вот она:// -- Clear list --
procedure TDataList.Clear;
var
CurrItem: PDataListItem;
Item: PDataListItem;
RRR: Integer;
begin
RRR := 0;
if FStartDataListItem <> nil then
begin
Item := FStartDataListItem;
while Item^.NextItem <> nil do // <<<< ТУТ!
begin
CurrItem := Item^.NextItem;
Item := Item^.NextItem;
if Assigned(FOnRemoveItem) then FOnRemoveItem(Self, CurrItem^.Data);
Dispose(CurrItem);
Inc(RRR);
end;
CurrItem := FStartDataListItem;
if Assigned(FOnRemoveItem) then FOnRemoveItem(Self, CurrItem^.Data);
Dispose(CurrItem);
FStartDataListItem := nil;
end;
end;
Смотрю в отладчике и вижу такое:
Item = $40959F0
Data = Inaccessible value
NextItem = Inaccessible value
Это капец, как такое может быть, ведь список прочитался. Проявляется на записи в середине списка, она и не последняя, и не первая :( Причем ошибка "плавающая", т.е. иногда возникает, иногда нет...
← →
Palladin © (2012-07-12 15:32) [1]while Item^.NextItem <> nil do // <<<< ТУТ!
Item - содержит мусор или указатель на освобожденный блок
← →
Palladin © (2012-07-12 15:35) [2]while Item^.NextItem <> nil do // <<<< ТУТ!
begin
CurrItem := Item^.NextItem; - запонил NextItem
Item := Item^.NextItem; - еще раз запомнил NextItem
if Assigned(FOnRemoveItem) then FOnRemoveItem(Self, CurrItem^.Data);
Dispose(CurrItem); - освободил память, теперь Item указывает в освобожденный блок
Inc(RRR);
end;
← →
Palladin © (2012-07-12 15:37) [3]Плавающая потому что данные в освобожденном блоке вполне могут жить и дальше некоторое время. По встречке тоже ездить можно.
← →
RWolf © (2012-07-12 15:42) [4]вообще, зачем строить цикл на Item^.NextItem, разве не проще следить непосредственно за Item? и начало списка освобождать отдельно не придётся.
← →
ПЛОВ © (2012-07-12 15:49) [5]Спасибо за помощь! :) Кажись понял, буду переделывать свою писанину :)
← →
ПЛОВ © (2012-07-12 15:51) [6]разве не проще следить непосредственно за Item?
Вроде:
читаем в Item начало списка, проверяем его на nil - если нет, ставим в начало NextItem, а Item освобождаем?
← →
Palladin © (2012-07-12 16:07) [7]
while Item <> nil do
begin
CurrItem := Item;
Item := Item^.NextItem;
if Assigned(FOnRemoveItem) then FOnRemoveItem(Self, CurrItem^.Data);
Dispose(CurrItem);
Inc(RRR);
end;
← →
Palladin © (2012-07-12 16:13) [8]и вообще, лишних движений многовато
procedure TDataList.Clear;
var
CurrItem: PDataListItem;
begin
while FStartDataListItem <> nil do
begin
CurrItem := FStartDataListItem;
FStartDataListItem := FStartDataListItem^.NextItem;
if Assigned(FOnRemoveItem) then
FOnRemoveItem(Self, CurrItem^.Data);
Dispose(CurrItem);
end;
end;
и всего делов
← →
MsGuns © (2012-07-12 16:13) [9]А почему нельзя пользоваться рабоче-крестьянским TList ?
← →
ПЛОВ © (2012-07-12 16:15) [10]Ага, спасибо! )
← →
ПЛОВ © (2012-07-12 16:22) [11]Можно и TList-ом, но я решил изобрести велосипед :)
← →
Dennis I. Komarov © (2012-07-12 21:35) [12]
> ПЛОВ © (12.07.12 15:26)
>
Иш ты какие люди появляются :)
Страницы: 1 вся ветка
Форум: "Прочее";
Текущий архив: 2013.03.22;
Скачать: [xml.tar.bz2];
Память: 0.47 MB
Время: 0.059 c