как правильно проверять существование обьекта ?
Модератор: Модераторы
- Attid
- долгожитель
- Сообщения: 2589
- Зарегистрирован: 27.10.2006 17:29:15
- Откуда: 44°32′23.63″N 41°2′25.2″E
- Контактная информация:
как правильно проверять существование обьекта ?
как правильно проверять существование обьекта ?
знаю два способа
generic_icons: TStringList;
if Assigned(generic_icons) then
and
if generic_icons <> nil then
оба не правильные и не работают =)
знаю два способа
generic_icons: TStringList;
if Assigned(generic_icons) then
and
if generic_icons <> nil then
оба не правильные и не работают =)
В fpc 2.2.4 под linux вроде правильно работает, проблема была в 2.2.0 или 2.2.2
А это всегда работает.
А это всегда работает.
Код: Выделить всё
if generic_icons is TStringList then Label1.Caption := 'Yes'
else Label1.Caption := 'No';
Logo писал(а):А это всегда работает.Код: Выделить всё
if generic_icons is TStringList then Label1.Caption := 'Yes'
else Label1.Caption := 'No';
Если переменная не инициализированна то получите ошибку доступа к памяти!
to Attid при объявлении объекта инициализируюте его как nil
Код: Выделить всё
var generic_icons: TStringList = nil;при уничтожении пользуйтесь процедурой FreeAndNil
Функция Assigned() тоже просто проверяет объект на NIL, так что если переменную не проинициализировать NIL'ом, то проверить, адрес в ней объекта или шелуха, невозможно.
Можно, конечно, проверять и так, как предложил Mr.Smart
Но лучше инициализировать, кода меньше...
Можно, конечно, проверять и так, как предложил Mr.Smart
Код: Выделить всё
Try
{Любое обращение к объекту}
Except
on EAccessViolation do
ShowMessage('ФигВам а не объект');
End;Но лучше инициализировать, кода меньше...
Mr.Smart писал(а):Logo писал(а):А это всегда работает.Код: Выделить всё
if generic_icons is TStringList then Label1.Caption := 'Yes'
else Label1.Caption := 'No';
Если переменная не инициализированна то получите ошибку доступа к памяти!
А проверить трудно?
Я так понял, что у Attid не стандартная ситуация. Не тот уровень у него, чтобы не понять если переменная не nil, то ее не стоит проверять на nil.
Logo писал(а):Я так понял, что у Attid не стандартная ситуация. Не тот уровень у него, чтобы не понять если переменная не nil, то ее не стоит проверять на nil.
Вопрос был имено о проверки на существование объекта, а не на проверку принадлежнасти к классу.
- Sergei I. Gorelkin
- энтузиаст
- Сообщения: 1409
- Зарегистрирован: 24.07.2005 14:40:41
- Откуда: Зеленоград
В общем случае это практически невозможно. Оператор 'is', завернутый в try..except, конечно, вернет true в случае, когда возможно прочитать sizeof(Pointer) байт памяти по заданному указателю и когда эти sizeof(Pointer) байт представляют собой указатель на VMT нужного нам класса, либо на VMT его потомка. Но это ничего не говорит ни о доступности, ни о состоянии остальных полей объекта. И даже если они доступны, это может оказаться только что уничтоженный объект, который будет переписан через пару миллисекунд...
Проще следить за тем, что записывается в переменную.
Проще следить за тем, что записывается в переменную.
Sergei I. Gorelkin писал(а):...И даже если они доступны, это может оказаться только что уничтоженный объект, который будет переписан через пару миллисекунд...
Проще следить за тем, что записывается в переменную.
Согласен на все 100%. Сам так и делаю.
Мне уже трудно найти код, написанный год назад, но при желании можно. Так вот там возникла ситуация, где гарантии нет, что неинициализированная переменная будет nil, - проверка на принадлежность к классу и выручила. Ситуация, что класс был удален, да может быть, но алгоритм программы это не предусматривал и я уверен, что этого не произойдет. Не по теории? - Конечно, но работает, а все мы по теории делаем? Что, никто классы не крякает для доступа к приватным полям? (хотя сам сейчас эту практику прекратил)
Зная по форуму Attid`а, мне и в голову не пришло, что он не смог разобраться с инициализацией переменных, я крупно сомневаюсь, что он не знал о том, что поля в классах инициализируются(обнуляются), а внешние переменные нет. Предположив, что ситуация нестандартная, я и предложил "нестандартный" метод проверки. Принимать его или нет - дело его.
- Attid
- долгожитель
- Сообщения: 2589
- Зарегистрирован: 27.10.2006 17:29:15
- Откуда: 44°32′23.63″N 41°2′25.2″E
- Контактная информация:
ой понаписали =)
1, польщен =) но гуру тоже могут ошибаться особенно в конце дня особенно в выходной =))
2, FreeAndNil это хорошо когда ты его должен освободить, но не помогает если его не создали. но передают как созданный.
чего и требовалось доказать. спасибо.
1, польщен =) но гуру тоже могут ошибаться особенно в конце дня особенно в выходной =))
2, FreeAndNil это хорошо когда ты его должен освободить, но не помогает если его не создали. но передают как созданный.
Sergei I. Gorelkin писал(а):В общем случае это практически невозможно.
чего и требовалось доказать. спасибо.
- Иван Шихалев
- энтузиаст
- Сообщения: 1138
- Зарегистрирован: 15.05.2006 11:26:13
- Откуда: Екатеринбург
- Контактная информация:
Attid писал(а):если его не создали. но передают как созданный
А в этом случае линейкой по рукам хорошо — помогает.
Тогда другая (уже практически осмысленная) задача. Есть объект, из него вызывается какая-то процедура. В результате сложной, непредсказуемой последовательности событий при выходе из этой процедуры может оказаться так что наш объект уже был уничтожен, соотв. обращаться к его полям и свойствам нельзя. Хочется отследить эту ситуацию и как-то обработать, например кинуть Abort. Как это сделать наиболее эффективно?
- Sergei I. Gorelkin
- энтузиаст
- Сообщения: 1409
- Зарегистрирован: 24.07.2005 14:40:41
- Откуда: Зеленоград
Так, вообще-то, оказваться не должно. И механизмы для того, чтобы этого не происходило, есть разные:
1) Интерфейсы+подсчет ссылок (объект не удаляется до тех пор, пока его кто-то использует)
2) Уведомление об уничтожении (TComponent.FreeNotification и сотоварищи)
3) Отложенное удаление (объект ставится в очередь и уничтожается несколько позже, когда уже можно. См. TForm.Release).
4) Не удалять вообще, в конце концов.
1) Интерфейсы+подсчет ссылок (объект не удаляется до тех пор, пока его кто-то использует)
2) Уведомление об уничтожении (TComponent.FreeNotification и сотоварищи)
3) Отложенное удаление (объект ставится в очередь и уничтожается несколько позже, когда уже можно. См. TForm.Release).
4) Не удалять вообще, в конце концов.
2 - для данной задачи не поможет
4 - это не решение проблемы, это отказ от решения.
1 и 3, да это путь. Но зачастую слишком сложный, может потребоваться перепроектировать пол системы.
Пример задачи: есть некий интерфейс-билдер с кнопочками и событиями OnClick. Что напишут в обработчике OnClick -
заранее неизвестно, могут убить и кнопочку, и форму на которой она лежит. В "обычном" языке - это приведет к AV - сам дурак.
А вот в "защищенной" среде - хотелось бы выдать цивильную ошибку...
4 - это не решение проблемы, это отказ от решения.
1 и 3, да это путь. Но зачастую слишком сложный, может потребоваться перепроектировать пол системы.
Пример задачи: есть некий интерфейс-билдер с кнопочками и событиями OnClick. Что напишут в обработчике OnClick -
заранее неизвестно, могут убить и кнопочку, и форму на которой она лежит. В "обычном" языке - это приведет к AV - сам дурак.
А вот в "защищенной" среде - хотелось бы выдать цивильную ошибку...
Max Rusov писал(а):Тогда другая (уже практически осмысленная) задача. Есть объект, из него вызывается какая-то процедура. В результате сложной, непредсказуемой последовательности событий при выходе из этой процедуры может оказаться так что наш объект уже был уничтожен, соотв. обращаться к его полям и свойствам нельзя. Хочется отследить эту ситуацию и как-то обработать, например кинуть Abort. Как это сделать наиболее эффективно?
Я у себя выкрутился из подобной ситуации таймером. После подачи команды на удаление, сначала блокируется доступ к объекту и запускается таймер на гарантированное время, чтобы все внутренние операции закончились. После истечения заданного времени, объект уничтожается. Можно и счетчик обращений с блокировкой применить, но с таймером оказалось проще.
Добавлено спустя 11 минут 26 секунд:
Max Rusov писал(а):Пример задачи: есть некий интерфейс-билдер с кнопочками и событиями OnClick. Что напишут в обработчике OnClick -
заранее неизвестно, могут убить и кнопочку, и форму на которой она лежит. В "обычном" языке - это приведет к AV - сам дурак.
А вот в "защищенной" среде - хотелось бы выдать цивильную ошибку...
Наверное переписывать Destroy и вводить проверку, если вызов сделан от потомка, то блокировать. Хотя, как это реализовать, на данный момент не представляю.
