Top.Mail.Ru
Мастера DELPHI, Delphi programming community Титульная страница Поиск, карта сайта Написать письмо 
| Новости | Поиск | FAQ | Статьи | Книги | Новости VCL |
| Форумы ЧАТ | Орешник | KOL и MCK |
Форумы -» Основная («Начинающим»)/ Базы / WinAPI / Компоненты / Сети / Media / Игры / Corba и COM / KOL / FreePascal / .Net / Прочее / RSDN.ORG

« предыдущая ветвь | форум | следующая ветвь »

Преобразование Untyped, что посоветуете? [D7, Win2k, WinXP]


gosha73 ©   (2006-11-16 01:58:00) 

Здравствуйте уважаемые.
Работаю с интерфейсами написанными другими программерами на дельфи. И тут в описании интерфейса вижу метод :
procedure OnUniqMessage(Message: Word; const Rec);
Т.е. есть список сообщений, который прилагается к интерфейсу и есть все соответсвующие сообщениям структуры. В зависимости от сообщения в Rec записываются различные структуры, в том числе различные по размеру и членам. Насколько это грамотно и безопасно хочу понять.
На той стороне программеры обрабатывают сообщения таким образом:
...
type
  TSome1 = record
    Val1: Integer;
    Str1: WideString;
  end;

  TSome2 = record
    Str1: WideString;
    Str2: WideString;
    Vis: Boolean;
  end;
...

procedure THdlr.OnUniqMessage(Message: Word; const Rec);
var Some1: TSome1;
    Some2: TSome2;
    ...
begin
 case Message of
  MSG_1: Some1 := TSome1(Rec);
  MSG_2: Some2 := TSome2(Rec);
  .....
 end;
 .....
end;

Что посоветуете? Может еще что-то надо проверять прежде чем нетипизированный Rec копировать в разные структуры?


gosha73   (2006-11-16 17:27:00) [1]


> Anatoly Podgoretsky ©   (16.11.06 11:52) [12]


> Так как все таки с размером структур то, проверил?

Да попробовал. Проверял. Но задумка кмк бесполезна. Обезопаситься максимально можно только с типизацией, как большинство и предложило. Иначе идем поперек правилам дельфи как строготипизированного языка.
Тот, кто придумал такой обработчик сообщений, тот раньше на си программировал, а я как человек не привыкший к таким вольностям в языке насторожился сразу увидев такое "безобразие". В дельфи с нетипизированными параметрами приходится иногда работать, в основном с различными буферами, но чтобы так записи передавать, это я не проходил в жизни еще. Ну теперь прошел.

И вам спасибо Сергей М. и iva.


iva   (2006-11-16 12:36:00) [2]

imho
Я бы попробовал сделать интерфейсный модуль в котором бы описал

 myOnUniqMessage(Hndlr:THndlr;Some:TSome1); overload;
 myOnUniqMessage(Hndlr:THndlr;Some:TSome2); overload;
 myOnUniqMessage(Hndlr:THndlr;Some:TSome3); overload;
 myOnUniqMessage(Hndlr:THndlr;Some:TSome4); overload;
....
procedure myOnUniqMessage(Hndlr:THndlr;Some:TSome1);
begin
 Hndlr.OnUniqMessage(MSG_1, Some);
end;  
procedure myOnUniqMessage(Hndlr:THndlr;Some:TSome2);
begin
 Hndlr.OnUniqMessage(MSG_2, Some);
end;


а вызов из программы был бы таким
 myOnUniqMessage(Hndlr, Some as TSome2);


Anatoly Podgoretsky   (2006-11-16 11:53:00) [3]

> Сергей М.  (16.11.2006 10:55:10)  [10]

Или это


Anatoly Podgoretsky   (2006-11-16 11:52:00) [4]

> gosha73  (16.11.2006 10:46:09)  [9]

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

Так как все таки с размером структур то, проверил?


evvcom   (2006-11-16 11:51:00) [5]

> [9] gosha73   (16.11.06 10:46)
> одназначную идентификацию обезопасить от любого горе программиста,
> ошибись который, повлечет собой ошибку доступа памяти в
> ядре программы

Я утверждаю, что на 100% обезопаситься от горе программиста невозможно! Ну и что страшного в том, что получишь AV? По идее это на этапе разработки/тестирования уже должно вылезти. А передача размера структуры тебя не обезопасит, только увеличит размер программы. Что помешает горе-программисту запросить в куче 2 байта, а передать в функцию размер в мегабайт? Ничего. Потому, имхо, это лишнее.

> [8] Anatoly Podgoretsky ©   (16.11.06 10:18)
> Если это константы, то какая проблема, одназначная идентификация
> структуры, поскольку это идентификатор и есть.

Полностью поддерживаю.


Сергей М.   (2006-11-16 10:55:00) [6]


> идентификацию обезопасить от любого горе программиста


От этого спасают объекты, реализующие интерфейсы-наследники IUnknown.


gosha73   (2006-11-16 10:46:00) [7]

Спасибо за советы. Да действительно, размер можно сделать первым членом записи.

Anatoly Podgoretsky, да это константы, но хочется и одназначную идентификацию обезопасить от любого горе программиста, ошибись который, повлечет собой ошибку доступа памяти в ядре программы.


Anatoly Podgoretsky   (2006-11-16 10:18:00) [8]

> evvcom  (16.11.2006 09:16:07)  [7]

Интуиция=телепатия

Если это константы, то какая проблема, одназначная идентификация структуры, поскольку это идентификатор и есть.

> Обычно, размер добавляют первым членом в записи

Все таки предлагаю вывести размер первой и второй структуры в диалог.


evvcom   (2006-11-16 09:16:00) [9]

> [0] gosha73   (16.11.06 01:58)
> procedure THdlr.OnUniqMessage(Message: Word; const Rec);
> var Some1: TSome1;
>    Some2: TSome2;

Я бы написал так:
var
 Some1: TSome1 absolute Rec;
 Some2: TSome2 absolute Rec;

Тогда фигня
> case Message of
>  MSG_1: Some1 := TSome1(Rec);
>  MSG_2: Some2 := TSome2(Rec);
>  .....
> end;
вообще не нужна, уже все присвоено :)

> [3] gosha73   (16.11.06 02:29)
> Хочу предложить им добавить в метод еще параметр размера
> передаваемой записи, что-то вроде этого:
> procedure OnUniqMessage(Message: Word; const Rec; RecSize:
> LongInt);

Обычно, размер добавляют первым членом в записи. Можно, конечно, но имхо, это лишнее. Лишняя проверка, которая все равно на 100% от ошибки программиста не избавит.

> [5] Anatoly Podgoretsky ©   (16.11.06 08:44)
> Нигде не видать определения MSG_N

Да вроде как и так интуитивно понятно, что это Word-константы.


Anatoly Podgoretsky   (2006-11-16 08:45:00) [10]

> gosha73  (16.11.2006 02:29:03)  [3]

А ты не хочешь вывести размер в ShowMessage?


Anatoly Podgoretsky   (2006-11-16 08:44:00) [11]

> gosha73  (16.11.2006 01:58:00)  [0]

Нигде не видать определения MSG_N

Без него нет предмета для разговора.


Eraser   (2006-11-16 03:09:00) [12]

> [3] gosha73   (16.11.06 02:29)

1. в данном случае нужно передавать не запись, а указатель на запись.
2. никаких доп. проверок не нужно, ведь есть Message, который должен однозначно пояснять, что находится в структуре.


gosha73   (2006-11-16 02:29:00) [13]

Хочу предложить им добавить в метод еще параметр размера передаваемой записи, что-то вроде этого:
procedure OnUniqMessage(Message: Word; const Rec; RecSize: LongInt);
Тогда они бы могли проверять размер записи с полученным, прежде чем преобразовывать нетипизированный параметр в запись.
К примеру так:
procedure THdlr.OnUniqMessage(Message: Word; const Rec; RecSize: LongInt);
var Some1: TSome1;
   ...
begin
case Message of
 MSG_1: begin if (RecSize = SizeOf(TSome1)) then Some1 := TSome1(Rec);end;
 .....
end;
.....
end;

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


Eraser   (2006-11-16 02:07:00) [14]

> [0] gosha73   (16.11.06 01:58)

мен сильно смущает использование WideString в записях...


gosha73   (2006-11-16 02:07:00) [15]

Ах да, а я отправляю эти сообщения из своей программы через интерфейс таким образом:
....
var Some1: TSome1;
begin
  Some1.Val1 := Sender.Tag;
  Some1.Str1 := Sender.WideStrCaption;
  Hndlr.OnUniqMessage(MSG_1, Some1);
end;
...

Во всех этих примерах всё работает, главное не перепутать сообещния и соответсвующие им структуры, но надежность и стабильность меня сильно беспокоят. Вот и обращаюсь к вам, как к более опытным.


Наверх

Титульная страница Поиск, карта сайта Написать письмо