[РЕШЕНО] Интерфейс и явный вызов деструктора

Вопросы программирования на Free Pascal, использования компилятора и утилит.

Модератор: Модераторы

Ответить
Аватара пользователя
Brainenjii
энтузиаст
Сообщения: 1351
Зарегистрирован: 10.05.2007 00:04:46

[РЕШЕНО] Интерфейс и явный вызов деструктора

Сообщение Brainenjii »

Никогда не работал с интерфейсами (старался обходиться классами и наследованием). Вот решил применить интерфейс (не относящийся к проблеме код убран):

Код: Выделить всё

Var
  aObject: BObjectClass;
  aManager: BManagerClass;
  aForm: BFormStatusClass;
Begin
  aObject := nil;
  aManager := nil;
  With CurrentThread Do
    Begin
      If HasParam('Activity') Then
        Begin
          aObject := ActivityManager.ChangeActivity(ByInteger('Activity'));
          aManager :=ActivityManager;
        End;
      (aObject As IStatus).SetStatus(bsWork);
      aObject.Burn; // <- Ошибка
    End;

Если мы уберем строку (aObject As IStatus).SetStatus(bsWork); - исключение не поднимется. Если мы опишем:

Код: Выделить всё

Var
  aObject: BObjectClass;
  aManager: BManagerClass;
  aForm: BFormStatusClass;
Begin
  aObject := nil;
  aManager := nil;
  With CurrentThread Do
    Begin
      If HasParam('Activity') Then
        Begin
          aObject := ActivityManager.ChangeActivity(ByInteger('Activity'));
          aManager :=ActivityManager;
        End;
      BActivityClass(aObject).SetStatus(bsWork);
      aObject.Burn; // <- теперь ошибки нет
    End;

то опять же, код выполнится замечательно. Что происходит с aObject после (aObject As IStatus).SetStatus(bsWork);?
Последний раз редактировалось Brainenjii 25.07.2011 14:57:30, всего редактировалось 2 раза.
Аватара пользователя
hinst
энтузиаст
Сообщения: 781
Зарегистрирован: 12.04.2008 18:32:38

Сообщение hinst »

а может быть, ошибка на предыдущей строке? Отладчик же иногда показывает на следующую строчку после той, на которой произошло исключение
Аватара пользователя
Brainenjii
энтузиаст
Сообщения: 1351
Зарегистрирован: 10.05.2007 00:04:46

Сообщение Brainenjii »

Боюсь, нет - отладчик останавливается именно в деструторе Burn, попробовал вставить отладочную строку после вызова интерфейсной функции - она отработала. Но на Burn все-равно ловлю исключение...

Добавлено спустя 14 минут 10 секунд:
тут нашёл в интернетах -
delphimaster.ru писал(а):Для потомков TInterfacedObject нельзя явно вызывать деструктор. Это происходит автоматически при обнулении кол-ва ссылок.

Если это так, то как быть?
Аватара пользователя
hinst
энтузиаст
Сообщения: 781
Зарегистрирован: 12.04.2008 18:32:38

Сообщение hinst »

Щито? Burn - это какой такой деструктор. Free надо юзать.
Во-вторых, как быть с деструктором: напиши

Код: Выделить всё

aObject:=nil

Подсчёт ссылок же. Когда объект (который интерфейс) увидит, что на него нет больше ссылок, он освободит свою душу
А можешь и не писать, ведь при выходе из процедуры он освободится и так
Аватара пользователя
Brainenjii
энтузиаст
Сообщения: 1351
Зарегистрирован: 10.05.2007 00:04:46

Сообщение Brainenjii »

Угу... Т.е. если я использую интерфейсы, то уничтожать я не должен, а должен обнулять... Сейчас попробовал - всё прошло, и даже в Burn зашло, когда все ссылки кончились... Но тогда мне придётся перелопатить уйму кода - убрать все явные деструкторы...
Есть какой-нибудь способы обмануть счетчик ссылок? A то и интерфейсы хочется, и деструторы явно вызывать ^_^
Аватара пользователя
hinst
энтузиаст
Сообщения: 781
Зарегистрирован: 12.04.2008 18:32:38

Сообщение hinst »

когда ты делаешь свой класс реализующим интерфейс, то ты можешь перекрыть методы _addref и _release, или как там они называются. Они будут вызываться каждый раз добавляется новая ссылка на объект или пропадает существующая ссылка. Вот их и перекрываешь. По дефолту там стоит, насколько я знаю, но это можно уточнить

Код: Выделить всё

if refcount = 0 then Free;

Вот ссылочка на статью http://www.freepascal.org/docs-html/rtl ... known.html

И, в общем, перекрыв руками эти два метода, ты можешь заставать вести себя объект в зависимости от увеличения и уменьшения количества ссылок на него так, как тебе хочется
Аватара пользователя
Brainenjii
энтузиаст
Сообщения: 1351
Зарегистрирован: 10.05.2007 00:04:46

Сообщение Brainenjii »

Нашёл это, спасибо. Но даже убрав автоматическую очистку при frefcount = 0 - все-равно вызывается Access Violation, если объект уже уничтожен (по всей видимости при входе в _Release: Longint :-(

Добавлено спустя 12 минут 15 секунд:
Можно ли избавиться от механизма подсчета ссылок вообще?
Аватара пользователя
hinst
энтузиаст
Сообщения: 781
Зарегистрирован: 12.04.2008 18:32:38

Сообщение hinst »

1. А override написал?
2. А проверку self <> nil в своём методе написал?
Odyssey
энтузиаст
Сообщения: 580
Зарегистрирован: 29.11.2007 16:32:24

Сообщение Odyssey »

Brainenjii писал(а):Можно ли избавиться от механизма подсчета ссылок вообще?

Если я правильно понимаю, то:
* можно переключить вид интерфейсов с COM на CORBA с помощью {$interfaces CORBA}, у CORBA-интерфейсов автоматического подсчёта ссылок нет (пруф);
* при использовании CORBA-интерфейсов не нужно наследоваться от TInterfacedObject (пруф).
Аватара пользователя
Brainenjii
энтузиаст
Сообщения: 1351
Зарегистрирован: 10.05.2007 00:04:46

Сообщение Brainenjii »

Круто! Спасибо, наверняка это решит проблему (сейчас уже реализовал как привычно - через базовый класс).
Ответить