Ссылка на объект, уничтожение и проверка на NULL

Clarion, Clarion 7

Модератор: Дед Пахом

Правила форума
При написании вопроса или обсуждении проблемы, не забывайте указывать версию Clarion который Вы используете.
А так же пользуйтесь спец. тегами при вставке исходников!!!
Ответить
Аватара пользователя
StillZero
Ветеран
Сообщения: 458
Зарегистрирован: 06 Июль 2005, 2:17
Откуда: Хабаровск
Поблагодарили: 1 раз
Контактная информация:

Ссылка на объект, уничтожение и проверка на NULL

Сообщение StillZero »

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

! описание примера:
! есть достаточно большой класс, работающий примерно по такой же схеме, как и представленный ниже код
! 1. я создаю объект в одной процедуре, передаю его адрес в другую процедуру, в которой этот объект уничтожается.
! 2. при выходе из первой процедуры, есть проверка - уничтожен ли объект, если нет, то я его уничтожаю.
! 3. а клара и говорит, что объект не был уничтожен, при попытке dispose прога валится по GPF.
! данный пример не валится, но процедура Destruct вызывается два раза

! вопросы:
! почему так происходит?
! и как проверять, на то что объект был уничтожен при таком случае?

! примечание: схема передачи объекта в процедуру именно такая, другая схема не устраивает

 PROGRAM
 MAP
   Main()
   RefProc(LONG inAddr)
 END

GlobalClass CLASS,TYPE ! описание глобального класса
Prop           LONG
Construct      PROCEDURE
Destruct       PROCEDURE
            END

 code
 Main()

Main PROCEDURE
LocalClass     &GlobalClass                        ! ссылка на локальный объект
 code
 LocalClass &= NEW GlobalClass                     ! создали локальный объект
 LocalClass.Prop = 10                              ! присвоили значение свойству

 RefProc(address(LocalClass))                      ! вызываем другую процедуру и передаем в нее адрес локального объекта

 if LocalClass &= NULL                             ! если объект уже уничтожен
    message('= (NULL)')                            ! то покажем что он уничтожен
 else
    message('не равно NULL !!!')                   ! а если еще жив, то убъем
    dispose(LocalClass)
 end


RefProc PROCEDURE(LONG inAddr)                     ! процедура, в которой убивается передаваемый объект
ref            &GlobalClass                        ! ссылка
 code
 ref &= (inAddr)                                   ! сошлемся на тот объект, адрес которого передали
 message(ref.Prop)                                 ! на всякий пожарный покажем что там за значение
 dispose(ref)                                      ! убъем объект

GlobalClass.Construct      PROCEDURE
 code
 message('Construct')

GlobalClass.Destruct       PROCEDURE               ! деструктор вызывается в данном примере 2 раза !!!
 code
 message('Destruct')

Аватара пользователя
Andrew Listiev
Активист
Сообщения: 166
Зарегистрирован: 07 Июль 2005, 11:16
Откуда: Латвия, Рига

Сообщение Andrew Listiev »

Клара какая? На последнем билде шестерки не валиться!
Аватара пользователя
Andrew™
SQL профи
Сообщения: 651
Зарегистрирован: 05 Июль 2005, 16:32
Откуда: Москва, Зеленоград

Сообщение Andrew™ »

совершенно неправильный код!!!
кто сказал что после DISPOSE(ref), ref - указатель на объект, обNULLится указатель на этот же объект в другой процедуре.
просто LocalClass будет ссылатьcя на несуществующий объект.

твой алгоритм в простом варианте равен следующему:

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

a &GlobalClass
b &GlobalClass
  CODE
 a &= NEW GlobalClass
 b &= a
 DISPOSE(a) ! а и б это самостоятельные указатели, и при убивании объекта по первому указателю, значение - указатель в b остаётся и следующий код неправильный
 IF ~(b &= NULL)
   DISPOSE(b)
 END
в твоём случае надо делать примерно так:

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

! описание примера: 
! есть достаточно большой класс, работающий примерно по такой же схеме, как и представленный ниже код 
! 1. я создаю объект в одной процедуре, передаю его адрес в другую процедуру, в которой этот объект уничтожается. 
! 2. при выходе из первой процедуры, есть проверка - уничтожен ли объект, если нет, то я его уничтожаю. 
! 3. а клара и говорит, что объект не был уничтожен, при попытке dispose прога валится по GPF. 
! данный пример не валится, но процедура Destruct вызывается два раза 

! вопросы: 
! почему так происходит? 
! и как проверять, на то что объект был уничтожен при таком случае? 

! примечание: схема передачи объекта в процедуру именно такая, другая схема не устраивает 

 PROGRAM 
 MAP 
   Main() 
   RefProc(LONG inAddr)
 END



GlobalClass CLASS,TYPE ! описание глобального класса 
Prop           LONG 
Construct      PROCEDURE()
Destruct       PROCEDURE(),VIRTUAL
            END

GlobalClassMgr  CLASS
object          &GlobalClass
Construct       PROCEDURE()
CreateObject    PROCEDURE(),*GlobalClass
DeleteObject    PROCEDURE()
Destruct        PROCEDURE(),VIRTUAL
 END
 code

 Main() 

GlobalClassMgr.Construct       PROCEDURE
    CODE
 SELF.object &= NULL
GlobalClassMgr.Destruct        PROCEDURE
    CODE
 SELF.DeleteObject()
GlobalClassMgr.CreateObject    FUNCTION
    CODE
 SELF.DeleteObject
 SELF.object &= NEW GlobalClass
 RETURN SELF.object

GlobalClassMgr.DeleteObject    PROCEDURE
    CODE
 IF SELF.object &= NULL THEN RETURN.
 DISPOSE(SELF.object)
 SELF.object &= NULL

Main PROCEDURE 
LocalClass   &GlobalClass                          ! ссылка на локальный объект
tmp          GlobalClassMgr
 code 
 LocalClass &= tmp.createObject()                  ! создали локальный объект
 LocalClass.Prop = 10                              ! присвоили значение свойству 

 RefProc(address(tmp))                             ! вызываем другую процедуру и передаем в нее адрес локального объекта

RefProc PROCEDURE(LONG inAddr)                     ! процедура, в которой убивается передаваемый объект 
ref            &GlobalClassMgr                     ! ссылка
 code
 ref &= (inAddr)                                   ! сошлемся на тот объект, адрес которого передали 
 message(ref.object.Prop)                          ! на всякий пожарный покажем что там за значение
 ref.DeleteObject()                                ! убъем объект

GlobalClass.Construct      PROCEDURE 
 code 
 message('Construct') 

GlobalClass.Destruct       PROCEDURE               ! деструктор вызывается в данном примере 2 раза !!! 
 code 
 message('Destruct') 
Аватара пользователя
Andrew™
SQL профи
Сообщения: 651
Зарегистрирован: 05 Июль 2005, 16:32
Откуда: Москва, Зеленоград

Сообщение Andrew™ »

вот если бы была возможность проверить валидность указателся...
ну ссылается на что то, а это что то есть?

но лучше так как я написал

в твоём случае, если это не в потоках, То можно передавать не по адресу а по указателю, то и проблемы бы не было, т к это была бы одна переменная типа указатель
Аватара пользователя
Andrew™
SQL профи
Сообщения: 651
Зарегистрирован: 05 Июль 2005, 16:32
Откуда: Москва, Зеленоград

Сообщение Andrew™ »

Andrew™ писал(а):вот если бы была возможность проверить валидность указателся...
ну ссылается на что то, а это что то есть?
сам себе отвечаю - НЕТ, т к может там что то и есть реальное, но УЖЕ может находится по этому адресу совершенно другой объенкт, и в результате всё равно GPF
Ответить