Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "Основная";
Текущий архив: 2003.05.01;
Скачать: [xml.tar.bz2];

Вниз

Как прервать конструктор ?   Найти похожие ветки 

 
Giemgo   (2003-04-13 00:26) [0]

Если в конструкторе при проверке определенных условий возникает ситуация, когда дальнейшая жизнь объекта не имеет смысла, как прервать Create ? Не вызывать же в самом create деструктор ? К тому же объект то еще не создан...

Вторичный вопрос - как дать понять вызывающему коду, что конструкция объекта отменяется ? Исключения использовать не могу, не подключен SysUtils (пишу на чистом WinApi).

Ну и напоследок - а если исключения можно использовать - то какое исключение надо генерировать ?


 
Набережных С.   (2003-04-13 09:36) [1]

program Project1;
{$APPTYPE CONSOLE}
uses
Windows;

type
TObj = class
public
constructor Create;
destructor Destroy; override;
end;

TExc = class
private
FMsg: string;
public
constructor Create(Msg: string);
destructor Destroy; override;
end;

{ TExc }

constructor TExc.Create(Msg: string);
begin
WriteLn("TExc.Create");
FMsg:=Msg;
end;

destructor TExc.Destroy;
begin
WriteLn("TExc.Destroy");
MessageBox(0, PChar(FMsg), "Error", MB_OK or MB_ICONERROR or MB_SYSTEMMODAL);
inherited;
end;

{ TObj }

constructor TObj.Create;
begin
WriteLn("TObj.Create");
raise TExc.Create("TObj creation failed!");
end;

destructor TObj.Destroy;
begin
WriteLn("TObj.Destroy");
inherited;
end;

begin
// Insert user code here
try
TObj.Create;
except
on E: TExc do WriteLn(">>>TExc exception");
else raise;
end;
ReadLn;
end.


Чего вы боитесь этого SysUtils?


 
Юрий Зотов   (2003-04-13 10:21) [2]

> Giemgo (13.04.03 00:26)

> как прервать Create ? Не вызывать же в самом create
> деструктор ?

Возбудить в конструкторе ЛЮБОЕ исключение. Объект будет уничтожен автоматически, деструктор тоже будет вызван автоматически. Дело в том что весь наш код конструктора компилятор окружает неявным блоком try-except и получается примерно следующее:

Создать_объект;
try
Наш_код_конструктора;
except
Уничтожить_объект;
raise;
end;


> К тому же объект то еще не создан...

Не так. Уже создан. Объект создается специальным скрытым кодом, который генерит компилятор. То есть, при ВХОДЕ в конструктор объект УЖЕ существует, а НАШ код в конструкторе только его инициализирует.


> как дать понять вызывающему коду, что конструкция объекта отменяется ?

Если при вызове конструктора происходит исключение - это и есть сигнал об отмене.


> Исключения использовать не могу, не подключен SysUtils (пишу
> на чистом WinApi).

Ну и пишите себе на здоровье, чем SysUtils помешал? Вот, предположим, пишем мы на чистом API. Написали несколько функций общего применения, вынесли их в отдельный модуль и подключили его к программе. Нормальная схема? Вполне нормальная. Так ведь и с SysUtils - точно то же самое. Функции SysUtils, которые не используются в Вашей программе, линковщик ве равно в нее не включит, так что при подключении SysUtils получаем мизерное увеличение размера кода (проверьте - увидите сами), зато массу удобств. Разве это не выгодно?

Ну, если уж это так принципиально, то сделайте так, как показал Набережных С.


> а если исключения можно использовать

Можно, без всяких проблем.


> то какое исключение надо генерировать ?

Любое.


 
Giemgo   (2003-04-13 13:02) [3]

SysUtils, которые не используются в Вашей программе, линковщик ве равно в нее не включит

Вы прямо для меня загадками говорите.
Давайте так. Делаю Build для своего проекта. Размер полученного exe 18444. Просто в uses добавляю SysUtils. Не использую ни одной процедуры оттуда, размер полученного кода 41984

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

По моему, в Дельфе всегда юнит полностью включается. Допустим, я добавил в тот же проект Forms - размер exe 368640. Может у меня линковщик неправильно работает, но он у меня всегда так работал.

И вообще, иначе зачем есть такая библиотека как KOL ? Ведь вся ее фишка как раз в этом, чтобы не подключать неиспользуемые вещи в программу, в отличии от VCL


 
Юрий Зотов   (2003-04-13 14:33) [4]

> Giemgo (13.04.03 13:02)

Размер увеличивается за счет кода инициализации/финализации подключенного модуля (и тех, на которые он, в свою очередь ссылается), их внутренних глобальных констант, переменных и пр.

Но код тех процедур/функций из этих модулей, которые ПО ФАКТУ
в программе не вызываются, в нее и не подключается.

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

Согласен, что для чистого API добавка в 23 K может быть неоправданно большой. Но у Вас же создается дельфишный объект - какое же это "чистое API"? Уже никак не чистое.

Хотя в конечном счете все это не так важно, поскольку:
"Ну, если уж это так принципиально, то сделайте так, как показал Набережных С.".

Так Вы избавитесь от SysUtils. А все остальное (по поводу raise в конструкторе) остается в силе.


 
Giemgo   (2003-04-13 15:09) [5]

Юрий Зотов, спасибо ! Я почти все понял.

А почему вы называете мой проект не чистым WinApi ? Ну да, у меня подключены модули типа Windows, но это только для того, чтобы самому не писать экспорт для функций WinApi

А почему Forms так увеличивает размер (килобайт так на 300). В initialization ничего криминального, глобальных констант тоже раз и обчелся ?


 
Anatoly Podgoretsky   (2003-04-13 15:27) [6]

Ну да ничего криминального, устанешь бегать по этому initialization и далее по ссылкам.
Ну так раз у тебя чистое АПИ то исключения тебе не нужны, коскольку Виндоус их не поддерживает ни в какой мере. Это совйств Дельфи и его классов.


 
Giemgo   (2003-04-13 15:37) [7]

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

А разве исключения - это свойства дельфи и его классов ? Я думал исключения - это и есть класс такой


 
Anatoly Podgoretsky   (2003-04-13 15:40) [8]

Тебя жесто обманули, не слушай их больше. Нет в WinApi никаких исключений.


 
Giemgo   (2003-04-13 15:49) [9]

А, точно, прошу прощения, не заметил RegisterFindGlobalComponentProc в Forms

Почему жестоко обманули ? Это вроде у Тейксера и Пачеко было... сейчас посмотрю... наверно, не так что-то понял


 
Anatoly Podgoretsky   (2003-04-13 15:52) [10]

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


 
Giemgo   (2003-04-13 15:59) [11]

Ну вот, нашел:

"В Delphi2 такого уже не было. Исключения Delphi6 полностью соответствуют исключениям Win32"

Но как понимаю, исключения win32 существуют только для библиотек.


 
Giemgo   (2003-04-13 16:23) [12]

Нет в WinApi никаких исключений.

Значит, все таки есть ? Или я опять не так что-то понимаю ?


 
[NIKEL]   (2003-04-13 16:44) [13]

->Нет в WinApi никаких исключений.


да... значит функции обработки ошибок и исключений есть, а самих исключений нету?? Господа Вы совсем с ума сошли ? :)

try/catch/finally никто не заприщал...



 
Giemgo   (2003-04-13 17:09) [14]

[NIKEL], ну вот, я про тоже. Просто Anatoly Podgoretsky утверждает, что исключений нету. Может что-то другое имеется в виду ?


 
[NIKEL]   (2003-04-13 17:16) [15]

Win32 API обеспечивает полную поддержку обработки ошибок и исключений.

Читайте о

AbnormalTermination
Beep :)
GetExceptionCode
GetExceptionInformation
GetLastError
SetErrorMode
SetLastError
SetLastErrorEx



 
Giemgo   (2003-04-13 18:13) [16]

Да, но вероятно Anatoly Podgoretsky имел в виду, что при возникновения исключения в windows ничего не передается, все обрабатывается самостоятельно.

Но в тоже время это не так для библиотек.


 
Giemgo   (2003-04-13 22:13) [17]

Anatoly Podgoretsky, я правильно понял ?


 
Giemgo   (2003-04-14 18:56) [18]

Все таки хотелось бы услышать мнение еще. Верна ли фраза:

Нет в WinApi никаких исключений


 
Бурундук   (2003-04-14 20:01) [19]

Giemgo (14.04.03 18:56)
а ты вызови RaiseException(123, 0, 0, nil)
и посмотри, есть ли в ВинАпи исключения.


 
Giemgo   (2003-04-14 21:02) [20]

External Exeption 7B

И чего ?


 
Giemgo   (2003-04-15 15:54) [21]

Ну так прояснит кто-нибудь ситуацию ?!

Нет в WinApi никаких исключений

Это правда или нет ? Очень странно, что все молчат... никто не знает ? Не верю


 
y-soft   (2003-04-15 16:59) [22]

Giemgo (15.04.03 15:54)
Ну так прояснит кто-нибудь ситуацию ?!

Нет в WinApi никаких исключений

Это правда или нет ? Очень странно, что все молчат... никто не знает ? Не верю


В Windows встроена поддержка исключений (structured exception handling, SEH), но для того, чтобы это работало, необходимо, чтобы компилятор генерировал специальный код (exception blocks). В MSDN/Platform SDK/Debugging and error handling механизмы описаны, если хотите еще больше подробностей, то почитайте у Рихтера главу про обработчики завершения.

А то складывается впечатление, что Вы поставили цель докoнать мастеров вместо того, чтобы разобраться самому.

P.S. MSDN находится на http://msdn.microsoft.com


 
Mikhail   (2003-04-15 17:03) [23]

А мастера-то куда-то сгинули :)


 
REA   (2003-04-15 17:15) [24]

Мне кажется, что исключения есть. И даже где-то на аппаратном уровне. По крайней мере у мат. сопроцессора. Иначе бы программы на некоторых материнских платах (а таких сечас довольно много) не висли. И выбрасывать в исключения можно не только классы. А в VC++ там этих исключений чертова туча разных типов (ну где-то штуки 3).


 
Игорь Шевченко   (2003-04-15 18:54) [25]


>Нет в WinApi никаких исключений


Есть. Читайте Рихтера, господа присяжные заседатели.

На худой конец win32.hlp

Exceptions can be initiated by hardware or software, and can occur in kernel-mode as well as user-mode code. Win32-based structured exception handling provides a single mechanism for the handling of kernel-mode and user-mode exceptions, both hardware- and software-generated.

The execution of certain instruction sequences can result in exceptions that are initiated by hardware. For example, an access violation is generated by the hardware when a process attempts to read from or write to a virtual address to which it does not have the appropriate access.
Events that require exception handling may also occur during execution of a software routine (for example, when an invalid parameter value is specified). When this happens, a thread can initiate an exception explicitly by calling the RaiseException function. This function enables the calling thread to specify information that describes the exception.



 
Giemgo   (2003-04-16 00:09) [26]

>Набережных С. (13.04.03 09:36)

в общем все понятно. Но где идет уничтожение созданного экземпляра TExc ?


 
Giemgo   (2003-04-16 10:45) [27]

Ведь нужно уничтожить TExc, иначе потеря памяти


 
Anatoly Podgoretsky   (2003-04-16 10:54) [28]

Giemgo (16.04.03 00:09)
Уничтожение ъкземпляра объекта идет в его деструкторе.


 
Digitman   (2003-04-16 11:58) [29]


> Giemgo


см. Anatoly Podgoretsky © (16.04.03 10:54)

под "деструктором" в дан.случае понимается не то, что ты видишь в теле метода Destroy (это лишь метод, позволяющий тебе явно выполнить какие-то действия над собственными полями объекта), а неявные действия, автоматически выполняемые в коде, сгенерированным компилятором, сразу же за завершением тела Destroy. Там, в этом неявном коде, собственно и деаллокируется память, распределенная под экземпляр. Собственно, метод Destroy и предлагается тебе для того, чтобы перед деаллокацией экземпляра выполнить какие-то собственные действия, например, по деаллокации аллокированных в отказавшем методе Create блоков памяти, дабы предотвратить мемлики.
Иными словами, за аллокацию/деаллокацию памяти под экз-р отвечает неявный код, автоматически генерируемый компилятором, а за аллокацию/деаллокацию памяти, явно выполняемую тобой, отвечает твой пользовательский код в теле методов Create/Destroy


 
Giemgo   (2003-04-16 18:30) [30]

Да это я понимаю !

raise TExc.Create("TObj creation failed!");

здесь, как понимаю, создается экземпляр TExc. Хотя странно, где ссылка на экземпляр ?
И где он уничтожается ? Где вызов TExc.Destroy ?


 
vuk   (2003-04-16 19:18) [31]

Деструкторы для исключений вызываются неявно.


 
Giemgo   (2003-04-16 23:07) [32]

1) Деструкторы для исключений вызываются неявно.

Сразу после обработки ?

2) А так значит можно любой класс создать ? Типа

procedure TForm1.Button1Click(Sender: TObject);
begin
raise TForm.Create(self);
end;

А почему мне выдается "Exception TForm in module project1.exe at 0004D95A" ?

Как-то не очень на исключение похоже :)


 
Набережных С.   (2003-04-17 18:30) [33]

>Giemgo (16.04.03 23:07)

raise TExc.Create("TObj creation failed!");

raise - директива, заставляющая компилятор в этом месте вызвать процедуру _RaiseExcept, которой параметром передается созданный нами объект TExc. Этот объект - просто носитель информации об исключении. _RaiseExcept выполняет некоторую подготовку и вызывает системную RaiseException, которая и есть "возбудитель исключения". Т.к. до этого в процедуре _ClassCreate был создан защитный фрейм, один из элементов которого - адрес обработчика исключений нашего приложения(если бы не было ни одного фрейма, то это был бы обработчик по умолчанию), то RaiseException вызовет этот обработчик. Данный обработчик, вставленный компилятором, уничтожит создаваемый объект(TObj), ссылка на который бала сохранена в TExcFrame, и вызовет _RaiseAgain, "продвинув" исключение далее. Так мы попадем в обработчик, описанный нами(блок Except-End). При этом этот обработчик получит ссылку на структуру TExceptionRecord, в которой, среди прочего, будет ссылка на объект TExc. Если мы обрабатываем исключение некоторого типа(а тип определяется классом переданного нами в raise объекта), то для этого объекта будет вызван деструктор и обработка исключения на этом закончится, иначе вновь будет вызван _RaiseAgain. При этом записи "On TExc do" отвечает класс TExc и любой его предок, а отсутствию "On" - любой класс.
Такова обработка исключений в первом приближении. Если интересует точнее и подробнее, то бери отладчик, залазь в модуль System, и - "вперед и с песней". Учиться думать самостоятельно надо. Программист думать должен, а не только вопросы по форумам рассыпать.


 
Giemgo   (2003-04-19 17:26) [34]

Набережных С, ты еще скажи, что вышенаписанное изучил глядя только в исходный код ? Ну тогда я тебе завидую

Говорят кто-то выучил Assembler в дебагере


 
vuk   (2003-04-19 17:39) [35]

to Giemgo:
А где это ещё можно изучить-то? Только там, в отладчике. Так что отладчик в руки - и вперёд!



Страницы: 1 вся ветка

Форум: "Основная";
Текущий архив: 2003.05.01;
Скачать: [xml.tar.bz2];

Наверх





Память: 0.55 MB
Время: 0.006 c
11-490
zetta
2002-07-25 12:44
2003.05.01
а так можно? почему-то ошибка 216 выскакивает


1-559
alexvan
2003-04-18 08:49
2003.05.01
Помогите с типом


14-730
td
2003-04-13 13:07
2003.05.01
опять про запрос


3-481
Nikos
2003-04-14 16:51
2003.05.01
помогите выбрать оптималную базу данных


3-474
VIB
2003-04-14 16:28
2003.05.01
DBGrid





Afrikaans Albanian Arabic Armenian Azerbaijani Basque Belarusian Bulgarian Catalan Chinese (Simplified) Chinese (Traditional) Croatian Czech Danish Dutch English Estonian Filipino Finnish French
Galician Georgian German Greek Haitian Creole Hebrew Hindi Hungarian Icelandic Indonesian Irish Italian Japanese Korean Latvian Lithuanian Macedonian Malay Maltese Norwegian
Persian Polish Portuguese Romanian Russian Serbian Slovak Slovenian Spanish Swahili Swedish Thai Turkish Ukrainian Urdu Vietnamese Welsh Yiddish Bengali Bosnian
Cebuano Esperanto Gujarati Hausa Hmong Igbo Javanese Kannada Khmer Lao Latin Maori Marathi Mongolian Nepali Punjabi Somali Tamil Telugu Yoruba
Zulu
Английский Французский Немецкий Итальянский Португальский Русский Испанский