Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате |
Форум программистов > Delphi: WinAPI и системное программирование > FreeAndNil |
Автор: Delphist 9.2.2007, 13:03 | ||
Почему FreeAndNil(obj) и MyFreeAndNil(obj) имеют разный результат выполнения. Объясните пожалуйста. |
Автор: Rennigth 9.2.2007, 13:11 |
В каком смысле? |
Автор: Delphist 9.2.2007, 13:32 | ||||
Почему я спрашиваю данный вопрос. В своей проге я использую DBGridEh. В одной из колонок при клике по ячейке появляется раскрывающийся список(LookUp поля). Так вот если я начну закрывать форму с этим гридом при раскрытом списке, то выскакивает ошибка. После трудоемкой трассировки выяснил место ошибки: Пример из DBGridEh:
Делаю так, ошибка исчезает
|
Автор: Rennigth 9.2.2007, 13:50 |
Точно не изза разницы как дестроить FColumns. Лезь в FColimns и смотри в чем проблема, и почему вылетает AV(думаю что AV). |
Автор: Delphist 9.2.2007, 14:03 |
Незнаю, незнаю... только вот AV пропадает. |
Автор: Rennigth 9.2.2007, 14:11 | ||
Разницы не вижу... ![]() В таких случаях помогает чашка кофе(или чего покрепче), шапка шамана и бубен. ![]() |
Автор: MetalFan 9.2.2007, 14:12 |
Delphist, если пропалает AV в одном месте, это еще не значит, что оно не вылезет в другом ;) |
Автор: MetalFan 9.2.2007, 14:54 | ||
с чего это вдруг?! оба способы НЕБЕЗОПАСНЫ если их применять неправильно... и вообще, программирование это небезопасная штука) так и лезут ошибки всякие! главное - уметь их правильно найти, локализовать и поправить. з.ы. это я к тому, что замена Free+:=nil на FreeAndNil - это не выход. есть деятели, что пишут так:
как вас такое? ошибки то не вылазят! значит тоже верное решение? а зачем их искать, если можно просто "спрятать" уведомления об их возниконовении?! |
Автор: Delphist 9.2.2007, 15:50 | ||
Вылезут. Потому как try execpt end; спасает от ошибок не связанных с памятью. А вот когда вы попытаетесь обраться к методу уже разрушенного объекта, при чем объект будет разрушен но не равен Nil а имеет адрес $0808088. Как вам это? |
Автор: MetalFan 9.2.2007, 16:11 |
невылезут, если AV происходит в пределах try..except. SEH "спасает"(читай ловит) от любых ошибок. а try except/finally end - это делфевая "обертка" над виндовым SEH. |
Автор: aktuba 9.2.2007, 17:54 | ||||
Может все дело в следующем:
Ты делаешь объекты Free и объекты = nil, после ты пытаешься присвоить "ничему" nil. Вот реализация FreeAndNil:
Попробуй так же... |
Автор: MetalFan 10.2.2007, 00:37 | ||
что-то не понял в смысл фразы. ничего не мешает сделать lSomeObj.Free; lSomeObj := nil; и ни к каким ошибкам это в идеале приводить не должно) з.ы. если конечно же объект раньше не убит. или при умирании ничего за собой не тащит. |
Автор: Alexeis 10.2.2007, 00:42 | ||||||
На счет
Могу сказать одно, Obj, не является уже указателем на на объект, а указателем на указатель на объект. Если передавать
то указатель на объект передается по значению, при этом объект Obj уничтожиться но исходный указатель не обнулиться, ведь передана не сама переменная указателя, а ее значение. Присвоение Obj := Nil; компилятор понимает не как зануление переменной объекта, которая на самом деле является указателем на объект, а зануление указателя на переменную, которая указывает на объект. Проблемы возникают из-за того что делфи неявно разыменовывает указатели, причем может делать это цепочечно для доступа к полям и методам, так как-будто и нет вообще указателей. Но при работе с такими переменными как с указателями (присвоение адреса это операция над указателем), неявное разименовывание запрещено, так это помешало бы проводить операции с указателями именно как с указателями, а не с их содержимым. Потому явное приведение
является единственно верным. Pointer(Obj) заставляет компилятор понять, то что нам нужна именно переменная объекта, а не указатель на нее и нужна она нам не для доступа к объекту, а для доступа к адресу записанному в ней (мы ведь приводим ее к указателю), запрещая компилятору различные интерепретации данной операции. Вообще операции приведения типа в делфи не являются таки простыми как это может показаться на первый взгляд. Приведение типов всегда является умными и может вызывать даже различные функции без нашего ведома. Так и в этом случае. Интерпретация в лоб Pointer(Obj) дала бы тот же результат, что и первый вариант, но в данном случае приведение является скорее сообщением компилятору о том что мы имеем ввиду записывая такую команду, ведь компилятор думает о том, что мы не знаем о создании неявного указателя на переменную объекта при передаче ее в качестве var параметра. Жуть да ![]() |
Автор: MetalFan 10.2.2007, 00:52 |
Alexeis, хорошо объяснил) аж я после 3х банок пива понял ![]() |
Автор: Bose 10.2.2007, 19:10 |
Delphist, не совсем в тему, но.... От загадочных AV в момент уничтожения DBGridEh можно попробовать избавиться путём установки свойства Datasource:=nil, перед уничтожением. |
Автор: Romikgy 10.2.2007, 22:19 | ||||||
добавлю и свои пару копеек имхо можно так
а здесь
имхо |