![]() |
| ||
|
|
Новости |
Поиск |
FAQ |
Статьи |
Книги |
Новости VCL
| | Форумы ЧАТ |
Орешник |
|
| |||
| |||
« предыдущая ветвь | форум | следующая ветвь »
Цикл по элементам TInterfaceList
harisma © (2011-06-06 11:40:00)Мне необходимо организовать цикл по элементам интерфейсного листа и при нахождении нужных элементов их выбросить из него. С этой целью написал следующую процедурку:
procedure CloseProtocols(const AProtocolID: WideString);
var
i: Integer;
LProtocolID: AnsiString;
IProtocol: IS4VPAProtocols;
begin
FProtocolList.Lock;
try
if (AProtocolID = '') then
begin
FProtocolList.Clear;
Exit;
end
for i := FProtocolList.Count - 1 downto 0 do
try
if (FProtocolList[i].QueryInterface(IS4VPAProtocols, IProtocol) = S_OK) then
begin
if (AProtocolID <> '') then
LProtocolID := FloatToString(IProtocol.ProtocolID);
if (AProtocolID = '') or (AProtocolID = LProtocolID) then
begin
IProtocol.CloseMean;
IProtocol.Server := nil;
if (AProtocolID <> '') then
FProtocolList.Remove(IProtocol);
end;
end;
except
end;
finally
FProtocolList.Unlock;
end;
end;
Но вот проблема: После того, как первый, удовлетворяющий условие элемент найден и удален из списка, попытка взять QueryInterface у следующего элемента списка приводит к AccessViolation.
Никак не пойму, в чем же проблема? Цикл вроде правильный. В списке присутствует 2 интерфейса. Прошу помощи...
harisma (2011-06-07 10:35:00) [1]
> до нуля не дойдет
А вот и не правда. Хотя, я ведь не привел полный текст процедуры. В моем случае именно и происходило разрушение интерфейса, не смотря на то что ссылка на него была в листе.
_Юрий (2011-06-06 20:27:00) [2]
> Ошибка решилась.
Ошибка скрылась. Данный код
> LProtocol := nil; - это я дописал
и так будет вызван компилятором сразу после выхода из локальной процедуры.
И никакое это не "разрушение интерфейса". Это уменьшение счетчика ссылок, который в данном случае до нуля не дойдет потому, что есть еще ссылка в листе.
Похоже, ты где-то память попортил.
harisma (2011-06-06 15:55:00) [3]Ошибка решилась. Проблема была в том, что когда я ЗАПОЛНЯЛ этот список интерфейсами, сами интерфейсы не разрушал в той процедуре, где заполнял. Другими словами было:
procedure ...
var
LProtocol: IProtocol;
...
begin
...
Lprotocol := CreateComObject(...)
LProtocol.Init.
FProtocolList.Add(Lprotocol);
end;
стало
procedure ...
var
LProtocol: IProtocol;
...
begin
...
Lprotocol := CreateComObject(...)
LProtocol.Init.
FProtocolList.Add(Lprotocol);
LProtocol := nil;- это я дописал
end;
anonims (2011-06-06 14:47:00) [4]
> IProtocol.Server := nil;
отключаем интерфейсный объект от сервера?
сам интерфейс остается.
Если другой интерфейс из списка тоже на этом объекте. то AV вероятно.
Iprotokol:=nil; наверное так?
makvell (2011-06-06 13:38:00) [5]А... там даунту. Сорри, проглядел :(
makvell (2011-06-06 13:37:00) [6]Предположение: Мы идем по i, длинна списка = 2, нашли первый, удалили. Второй стал первым, а мы пытаемся взять по i следующий, которого какбы и нет.
KSergey (2011-06-06 12:29:00) [7]FProtocolList.Remove(IProtocol);
Есть уверенность, что из списка здесь удаляется именно текущий i-й элемент? или я неправильно понимаю принцип работы TInterfaceList?
harisma (2011-06-06 12:17:00) [8]Так не помогает. Так и было у меня первоначально.
Ega23 (2011-06-06 12:07:00) [9]
> FProtocolList.Remove(IProtocol);
FProtocolList.Delete(i)