Ссылается ли указатель на компонент?

Вопросы программирования и использования среды Lazarus.

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

Ссылается ли указатель на компонент?

Сообщение jakyro » 22.08.2016 09:35:46

Как можно проверить, является ли BadPtr указателем на существующую форму или является ли BadForm существующей формой?

Переменная с указателем - пользовательская и нужно проверить форма ли это или кривой указатель...
Код: Выделить всё
procedure test;
var
  BadPtr: PtrInt;
  BadForm: TForm;
begin
  BadPtr := 12345678;
  { if ? then } { как проверить, ссылается ли указатель BadPtr на существующую форму }
    BadForm := TForm(BadPtr);
  { if ? then } { или тут проверить, является ли BadForm существующей формой }
    BadForm.Show(); { тут уже выдаст ошибку, так как память не доступна }
end;
Аватара пользователя
jakyro
новенький
 
Сообщения: 38
Зарегистрирован: 22.08.2016 08:04:21

Re: Ссылается ли указатель на компонент?

Сообщение bormant » 22.08.2016 12:50:59

Аватара пользователя
bormant
постоялец
 
Сообщения: 408
Зарегистрирован: 21.03.2012 11:26:01

Re: Ссылается ли указатель на компонент?

Сообщение zub » 22.08.2016 13:21:50

В общем случае никак.
zub
долгожитель
 
Сообщения: 2887
Зарегистрирован: 14.11.2005 23:51:26

Re: Ссылается ли указатель на компонент?

Сообщение jakyro » 22.08.2016 16:23:44


И что это? Типа я такую банальную вещь не пробовал?
Дело то в том, что в lazarus оператор is добывает инфу где-то из самого объекта или т.п. Но объект не является объектом и выдаст ошибку доступа к памяти.

Я давно делал костыль на delphi 2007, там можно было отловить это исключение и обработать, закрыть глаза на ошибку и думать что объект битый.
Но в lazarus даже такое что-то не работает. Может как-то иначе исключения нужно настроить, не знаю...

А способов я много перепробовал, искал и т.д.
Думаю что тут получится только какой-то редкой функцией или функциями по работе с памятью, читать, анализировать...

Отладка lazarus ведь как-то определяет, что один указатель - это структура TForm, другой - это неизвестный указатель.
Как-то всё таки можно, но сложно...
Аватара пользователя
jakyro
новенький
 
Сообщения: 38
Зарегистрирован: 22.08.2016 08:04:21

Re: Ссылается ли указатель на компонент?

Сообщение zub » 22.08.2016 16:55:16

jakyro
>>А способов я много перепробовал, искал и т.д
Не валидлный указатель это баг - надо исключить возможность его появления а не пытаться проверить на валидность.

>>Отладка lazarus ведь как-то определяет, что один указатель - это структура TForm, другой - это неизвестный указатель.
Отладчик ниче не проверяет, если указатель указывает на область данных приложения, но не на валидные данные, он покажет мусор. Если на невыделенную память - скажет что неможет прочитать.

>>Как-то всё таки можно, но сложно...
Уничтожаешь данные в куче - будь добр обниль все указатели на них. тогда проверка на nil равна проверке на валидность
zub
долгожитель
 
Сообщения: 2887
Зарегистрирован: 14.11.2005 23:51:26

Re: Ссылается ли указатель на компонент?

Сообщение скалогрыз » 22.08.2016 17:46:21

jakyro писал(а):Я давно делал костыль на delphi 2007, там можно было отловить это исключение и обработать, закрыть глаза на ошибку и думать что объект битый.
Но в lazarus даже такое что-то не работает. Может как-то иначе исключения нужно настроить, не знаю.

если try..catch и работал в Delphi, сообщая о неправильном указателе, то это просто везение.

При работе с объектами, у тебя вообще не должно быть ситуации проверять правильный/неправильный указатель. В общем-то ты и с указателями не должен работать.

Для решения проблемы я рекомендую переписать код, чтобы проблема исчезла как таковая.
Если кода нужно много переписывать, то я рекомендую переписать код.
скалогрыз
долгожитель
 
Сообщения: 1803
Зарегистрирован: 03.09.2008 02:36:48

Re: Ссылается ли указатель на компонент?

Сообщение jakyro » 22.08.2016 19:11:05

zub писал(а):Не валидлный указатель это баг - надо исключить возможность его появления а не пытаться проверить на валидность.

Т.е. ты признаёшь, что есть такое понятие как "валидный" и "не валидный" указатель, и оно допустимо, и как-то проверяется.
Вот у меня как раз та ситуация, где могут всплыть и не валидные указатели, и чтобы не крашить приложение, мне нужно эти ситуацию как-то обыграть, проверять указатели.

zub писал(а):Отладчик ниче не проверяет, если указатель указывает на область данных приложения, но не на валидные данные, он покажет мусор. Если на невыделенную память - скажет что неможет прочитать.

Верно. Это и нужно, для проверки указателя.

zub писал(а):Уничтожаешь данные в куче - будь добр обниль все указатели на них. тогда проверка на nil равна проверке на валидность

Организовать свой менеджер памяти? Что-то ты не верно понял вопрос... Пользователь вводит любой указатель, а программа должна определить, является ли указатель валидным, а не то что я там имею какую-то кучу указателей и их чекаю (именно этого я и хочу от менеджера памяти lazarus... ).

Это всё понятно, что я бы мог завести тот же банальный массив указателей и проверять, есть ли там такой указатель, если есть, то скорей всего он валиден (скорей всего, так как может и нет, так как его могут уничтожить и другие компоненты, библиотеки, процессы, <и тут ещё множество других вариантов>).

Но это был бы очередной костыль. Примерно тоже самое что и с исключениями в делфи (и нет, это не случай, там всё действительно можно обработать в исключениях (ответ к следующему комменту)).
Просто, возможно, в delphi 2007 лучше реализован механизм исключений, чем lazarus, либо иначе настроен, менее чувствителен, имеет другие варианты решения, помимо модальной ошибки.
А так же может влиять функциональность менеджера памяти и именно поэтому во многих ответах, в интернете, советуют использовать альтернативный менеджер памяти, с расширенными возможностями.


Просто я думал и всё ещё думаю, что в lazarus, pascal всё такие есть какой-то механизм, чтобы это реализовать, прочитать указатель, если он читаем и содержит указанную структуру.

И нужно кстати это для некого скриптового языка. Скриптовой язык ведь более динамичен и позволяет менять всё на ходу, а так же есть механизмы, трюки, хаки, дополнения для изменения того, что не меняется.
Можно сказать типа "не менять этот указатель любым возможным способом" (типа как константы в питоне, если понимаете о чем я), а можно реализовать валидацию. На худой конец тот самый массив указателей.

Ещё один банальный способ предложу, типа "читать определенный участок памяти, если он читаем и искать там зацепку, типа класс TForm, последовательность байт, сигнатуры и прочие".


Зашёл на форум, где вроде бы сообщество людей знающих pascal, lazarus. А в действительности сам же что-то объясняю, предлагаю варианты решения, а не пишу глупые отписки типа "ну сделай чтоб так не было"...
Мне нужно именно проверить указатель, чтобы сделать приложение более динамичным (и даже в случае, когда пользователь удалил компонент и пытается на него сослаться - приложение не крашилось, а обрабатывало исключение, не давая работать с не валидным указателем).
Неужели для языка такого уровня это не возможно?

Или просто вы с этим не сталкивались, не работали, возможно чего-то и не знаете... Можно такое предположить?
Это ведь не значит, что "так делать не надо" и "это не возможно".

Решение то я реализую в любом случае, просто думал мож тут скажут что-то, чего я не знал.

Добавлено спустя 21 минуту 25 секунд:
скалогрыз писал(а):если try..catch и работал в Delphi, сообщая о неправильном указателе, то это просто везение.

Нет, это не везенье, так можно обработать практически любую ситуацию, кроме фатальных (просто после фатальных приложение перестанет нормально функционировать, а так и это можно обработать).

Весь старый ui движок для скриптового языка работал на подобных трюках, позволяю приложению спокойно продолжить работу, а не крашиться при любом не валидном указателе.
Но он старый (2004)(а как же так, ведь делфи 2007, а вот так, был портирован с delphi 7), и библиотеки платные, и среда дорогая... Вот и хотелось бы переписать на альтернативной среде.

скалогрыз писал(а):При работе с объектами, у тебя вообще не должно быть ситуации проверять правильный/неправильный указатель. В общем-то ты и с указателями не должен работать.

Верно, я работаю не с объектами, а с указателями. А является ли указатель объектом или ничем, это уже нужно проверить.
Чтобы можно было это представить, опишу банальный пример, делаешь API или SDK, где взаимодействие производится только по указателям, вот собственно и не плохо было бы чекать эти указатели, так как весь SDK не может следить за всем тем, что творится в памяти LCL... Может. Если написать портянку... Вот поэтому такая банальная возможность, как проверка существования компонента по указателю, была бы совсем кстати.

скалогрыз писал(а):Для решения проблемы я рекомендую переписать код, чтобы проблема исчезла как таковая.
Если кода нужно много переписывать, то я рекомендую переписать код.

Так код и не написан.
Так как старый трюк с исключениями тут не работает, вот я и зашёл спросить, делать мне хранилище указателей, хоть для какой-то валидации, либо такой механизм присутствует в менеджере памяти lazarus и я могу проверить указатель на предмет присутствия в нём конкретной структуры.
По сути ведь это банальная задача для языка такого уровня: проверить читаема ли память, прочитать участок памяти, убедиться что в нем нет конкретной структуры или есть.
Аватара пользователя
jakyro
новенький
 
Сообщения: 38
Зарегистрирован: 22.08.2016 08:04:21

Re: Ссылается ли указатель на компонент?

Сообщение zub » 22.08.2016 19:37:44

>>Т.е. ты признаёшь, что есть такое понятие как "валидный" и "не валидный" указатель, и оно допустимо, и как-то проверяется.
Конечно есть валидные и невалидные, но это всё очень условно и в общем случае никак НЕ ПРОВЕРЯЕТСЯ
Код: Выделить всё
TMyData=record ... field1:string; ... end;
...
PMyData:=GetMem(sizeof(TMyData));
PMyData2:=pointer(PtrInt(PMyData)+1);

PMyData валидный? а PMyData2?
>>Вот у меня как раз та ситуация, где могут всплыть и не валидные указатели, и чтобы не крашить приложение, мне нужно эти ситуацию как-то обыграть, проверять указатели.
Эта ситуация называется кривой код. скалогрыз уже описал как эту ситуацию обиграть

>>А в действительности сам же что-то объясняю, предлагаю варианты решения, а не пишу глупые отписки типа "ну сделай чтоб так не было"...
Давай, костыляй "решения", потом незабудь зайти снова - признать что порол глупости))

Добавлено спустя 10 минут 56 секунд:
>>Весь старый ui движок для скриптового языка работал на подобных трюках
Свят-свят, неприведи господь)) тюфу*3
Предлагаю подумать на тему "почему в winapi юзаются хендлы, а не указатели, вот было бы круто если..." и возможно сделать какието выводы
zub
долгожитель
 
Сообщения: 2887
Зарегистрирован: 14.11.2005 23:51:26

Re: Ссылается ли указатель на компонент?

Сообщение скалогрыз » 22.08.2016 20:08:14

jakyro писал(а):Чтобы можно было это представить, опишу банальный пример, делаешь API или SDK, где взаимодействие производится только по указателям, вот собственно и не плохо было бы чекать эти указатели, так как весь SDK не может следить за всем тем, что творится в памяти LCL... Может. Если написать портянку... Вот поэтому такая банальная возможность, как проверка существования компонента по указателю, была бы совсем кстати.

Если ты пишешь этот самый API/SDK, то ты можешь просто вести список созданных твоим SDK "публичных" компонентов. (например, если компонент был создан внутри SDK, но "наружу" не выдаётся, в список его не нужно добавлять)
А функция может бегать по-этому списку (либо бинарый поиск, либо деревом - по вкусу) и проверять, есть ли указатель там или нет.

Но, если бы я писал SDK, я бы тупо забивал на такие вещи. Если пользователь этого самого SDK не может передать правильный указатель, то я имею полное моральное правно рухнуть к чертям.

Например, zub упомянул в WinAPI использование хендлов - система обеспечивает таки образом защиту, от переданной в неё фигни.
А вот, скажем в OSX (ни в карбоне, ни в коке), такой защиты нет, и если в системную функцию передана фигня, то приложение с чистой совестью просто упадёт. (В худшем случае, она может перестать выполнять обработчик, и окажется частично нерабочей).

jakyro писал(а):Так как старый трюк с исключениями тут не работает, вот я и зашёл спросить, делать мне хранилище указателей, хоть для какой-то валидации,


Такой трюк может работать. И он ещё лучше работает если запускать программу не из под отладчика.
jakyro писал(а):По сути ведь это банальная задача для языка такого уровня: проверить читаема ли память, прочитать участок памяти, убедиться что в нем нет конкретной структуры или есть.

Да, банальная, но только в том случае если не заботит вопрос производительности и объёма памяти.
Беготня по списку правильных указателей дело в принципе небыстрое.
Беготня по списку типизированных указателй, составленную на основе спискоа нетипизированных указателей вности дополнительные расходы на память (ведь нужно типизированные от нетипизированных отличать).
RTL паскаля идёт по принципу экономии памяти и времени, и ничего за тебя не делает.
скалогрыз
долгожитель
 
Сообщения: 1803
Зарегистрирован: 03.09.2008 02:36:48

Re: Ссылается ли указатель на компонент?

Сообщение jakyro » 22.08.2016 20:17:02

скалогрыз писал(а):то ты можешь просто вести список созданных твоим SDK "публичных" компонентов. (например, если компонент был создан внутри SDK, но "наружу" не выдаётся, в список его не нужно добавлять)
А функция может бегать по-этому списку (либо бинарый поиск, либо деревом - по вкусу) и проверять, есть ли указатель там или нет.

Да, это я и считаю глупым, затратным по времени, по ресурсам способом.
скалогрыз писал(а):Беготня по списку правильных указателей дело в принципе небыстрое.

Именно. Потому я ищу альтернативу, типа исключений в delphi 2007.

Добавлено спустя 3 минуты 59 секунд:
zub писал(а):Давай, костыляй "решения", потом незабудь зайти снова - признать что порол глупости))

Видать я сюда больше не вернусь ) )) ))) ))))

А варианты решения я тебе уже перечислил, просто они меня не устраивают по затрапезности времени и ресурсов.
Вот и ищу более простой способ, лаконичный, быстрый.

Ну и опять же, если кто-то не достаточно опытные программисты, узкой направленности, не работали с динамикой и т.д., то это не говорит о том, что это не возможно и это никому не нужно.
В бытовом хозяйстве это возможно и не нужно, но есть редкие, сложные проекты, где это может понадобиться.

Просто вот кину, мож почитаешь 2004 года то, о чем я говорю, понадобилось же кому-то... Правда тут сборник других хаков, хотя и try тоже есть.
http://hallvards.blogspot.ru/2004/06/hack-6checking-for-valid-object.html
Аватара пользователя
jakyro
новенький
 
Сообщения: 38
Зарегистрирован: 22.08.2016 08:04:21

Re: Ссылается ли указатель на компонент?

Сообщение zub » 22.08.2016 20:25:55

>>Просто вот кину, мож почитаешь 2004 года то, о чем я говорю, понадобилось же кому-то... Правда тут сборник других хаков, хотя и try тоже есть.
Просто если бы ты свою систему в 2004 или каком там далеком году основал не на хаках и трюках, она бы сейчас работала и не пищала. и незачем было бы вопрошать на неквалифицированных форумах))
От случая
Код: Выделить всё
  BadPtr := циферки;
  { if ? then } { как проверить, ссылается ли указатель BadPtr на существующую форму }
    BadForm := TForm(BadPtr);
  { if ? then } { или тут проверить, является ли BadForm существующей формой }
    BadForm.Show(); { тут уже выдаст ошибку, так как память не доступна }

Нет защиты, ты стреляешь себе в ноги, режешь яйца и горло... А форум виноват))
zub
долгожитель
 
Сообщения: 2887
Зарегистрирован: 14.11.2005 23:51:26

Re: Ссылается ли указатель на компонент?

Сообщение Лекс Айрин » 22.08.2016 20:37:00

jakyro писал(а):Именно. Потому я ищу альтернативу, типа исключений в delphi 2007.


Это, в среднем, не быстрее будет. Исключение очень трудозатратный механизм.

jakyro писал(а):Ну и опять же, если кто-то не достаточно опытные программисты, узкой направленности, не работали с динамикой и т.д., то это не говорит о том, что это не возможно и это никому не нужно.
В бытовом хозяйстве это возможно и не нужно, но есть редкие, сложные проекты, где это может понадобиться.


Очень тяжело представить проекты, где может понадобиться указатель в никуда. Обычно, все указатели сразу же оприходуются и не возникает особой необходимости в его проверке (за исключением равенства nil). Плюс поиск плавающих ошибок может привести к тому, что придется все переписать. Адресная арифметика хороша в четко выделенной области с натянутой поверх "сырых" данных структурой.

jakyro писал(а):Видать я сюда больше не вернусь ) )) ))) ))))


Ну и зря. Эмоцинальность одного-двух еще не повод расплеваться со всеми.

jakyro писал(а):Правда тут сборник других хаков, хотя и try тоже есть.


Ключевое слово хак. При смене версии компилятора/компонента его могут специально или случайно прикрыть. И тогда придется код срочно переделывать.
Аватара пользователя
Лекс Айрин
долгожитель
 
Сообщения: 5723
Зарегистрирован: 19.02.2013 16:54:51
Откуда: Волгоград

Re: Ссылается ли указатель на компонент?

Сообщение zub » 22.08.2016 20:51:51

Эмоции у автора поперли со второго поста. Сдержаней надо быть))
zub
долгожитель
 
Сообщения: 2887
Зарегистрирован: 14.11.2005 23:51:26

Re: Ссылается ли указатель на компонент?

Сообщение скалогрыз » 22.08.2016 20:57:05

jakyro писал(а):Да, это я и считаю глупым, затратным по времени, по ресурсам способом.

як так?
Ты же сначала написал:
jakyro писал(а):По сути ведь это банальная задача для языка такого уровня: проверить читаема ли память, прочитать участок памяти, убедиться что в нем нет конкретной структуры или есть.

Просто раз RTL такую возможность не предоставляет, она ложится на твои хрупкие плечи.
Если ты считаешь, что бегать по дереву/списку это медленно, то можешь завести себе массив элементов, на выдавать наружу не указатель а номер эелмента.

прям как винда:
Код: Выделить всё
procedure AddComponent(c: TComponent): THandle;
begin
  Result:=fCompCount;
  fComps[fCompCount]:=c;
  inc(fCompCount);
end;

function GetComponent(h: THandle): TComponent;
begin
  if isValidComponent(h) then Result:=fComps[h];
  else Result:=nil;
end;

function isValidComponent(h: THandle): Boolean;
begin
  Result:=(h>0)  and (h<fCompCount) and Assigned(fComps[fCompCount]);
end;

function CreateButton: THandle;
begin
  Result:=AddComponent(TButton.Create(nil))
end;

proedure SetButtonCaption(button :THandle; Caption: PWideChar);
var
  c : TComponent;
begin
  c:=isValidComponent(button);
  if Assigned(c) and (c is TButton) then TButton(c).Caption:=UTF8Encode(Caption);
end;

делоф-то!

jakyro писал(а):Именно. Потому я ищу альтернативу, типа исключений в delphi 2007.

В лазарусе она есть, и точно такая же. Тот же самый try..except. Только отладчик выключи.
Последний раз редактировалось скалогрыз 22.08.2016 21:17:50, всего редактировалось 1 раз.
скалогрыз
долгожитель
 
Сообщения: 1803
Зарегистрирован: 03.09.2008 02:36:48

Re: Ссылается ли указатель на компонент?

Сообщение Лекс Айрин » 22.08.2016 20:58:13

zub, не забывай, что мы тут уже притерлись друг к другу... а человек новый не всегда понимает стиль каждого, а пролистать форум и посмотреть не все догадываются.
Аватара пользователя
Лекс Айрин
долгожитель
 
Сообщения: 5723
Зарегистрирован: 19.02.2013 16:54:51
Откуда: Волгоград

След.

Вернуться в Lazarus

Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей и гости: 240

Рейтинг@Mail.ru