Главная страница
Top.Mail.Ru    Яндекс.Метрика
Текущий архив: 2005.09.04;
Скачать: CL | DM;

Вниз

"Проверь себя". Тест для начинающих.   Найти похожие ветки 

 
begin...end ©   (2005-08-03 19:07) [0]

Что такое класс? Что такое экземпляр класса? Как работает объект?

Часто в "Основной" конференции новички (и, к сожалению, не только новички) демонстрируют частичное или полное непонимание этого.

У меня есть несколько вопросов (ответы на них я знаю), касающихся внутреннего устройства объектов (не тех, которые object, а тех, которые экземпляры class) в Delphi. Эти вопросы я когда-то придумал сам (что называется, "от нечего делать"). Ни в коей мере не претендуя на роль учителя, предлагаю тем начинающим, кому это интересно, попробовать ответить на них. Возможно, у кого-нибудь в результате появится желание самостоятельно разобраться в этих или других вопросах программирования в Delphi. Ну а если это приведёт к уменьшению числа "слишком простых" вопросов в "Основной", то, думаю, все от этого только выиграют.

Подчеркну, что вопросы адресованы, в первую очередь, именно начинающим, поэтому прошу уважаемых Мастеров пока не давать своих ответов.

Вопросы я постарался расположить в порядке увеличения их сложности. Итак, начнём:

1. Возникнет ли исключение при выполнении кода TObject(nil).Free? А при выполнении TObject(nil).Destroy? Почему?

2. Возникнет ли исключение при выполнении выделенной строки в коде:

var
 C: TControl;
begin
 C := TControl.Create(nil);
 C.Free;
 C.Free
end


и почему?

3. Имеется класс:

type
 TMyClass = class
   class function ClassMethod: Integer;
   function Method: Integer;
 end;

class function TMyClass.ClassMethod: Integer;
begin
 Result := Integer(Self)
end;

function TMyClass.Method: Integer;
begin
 Result := Integer(Self)
end.


Если создать экземпляр этого класса и последовательно вызвать два этих метода, то они возвратят разные значения. Почему так происходит, ведь в них между begin и end написан одинаковый код? Как нужно изменить код одного из методов, чтобы возвращаемые значения были одинаковыми?

4. Будет ли создан экземпляр класса (т.е. будет ли выделена память для него) при выполнении выделенной строки?

var
 Obj: TObject;
begin
 Obj.Create
end.


5. Возникнет ли исключение при выполнении выделенной строки? Почему?

interface

type
 TMyClass = class
   procedure Method;
 end;

implementation

procedure TMyClass.Method;
begin
 ShowMessage("AV or not AV?")
end;

var
 C: TMyClass;
begin
 C := nil;
 C.Method
end.


Изменится ли ситуация, если метод Method сделать виртуальным? Почему?

6. Какое сообщение появится на экране после выполнения выделенной строки:

type
 TMyClass = class
   FWord: Word;
 end;

var
 C: TMyClass;
 B: Byte;
begin
 C := TMyClass.Create;
 try
   C.FWord := 512;
   B := PByte(Longword(C) + 4)^;
   ShowMessage(IntToStr(B))
 finally
   C.Free
 end
end


и почему?

7. Какое сообщение появится на экране после выполнения приведённого ниже кода? Почему?

interface

type
 TExObject = class
   IntField: Integer;
   procedure Show;
 end;

implementation

procedure TExObject.Show;
begin
 ShowMessage(IntToStr(IntField))
end;

const
 Arr: array [1..3] of Integer = (123, 456, 789);
begin
 TExObject(@Arr).Show
end.


8. Чему будет равно выделенное условие -- True или False? Почему? И что в этом условии сравнивается?

var
 Obj1: TObject;
 Obj2: TComponent;
begin
 Obj1 := TControl.Create(nil);
 Obj2 := TControl.Create(nil);
 try
   if PPointer(Obj1)^ = PPointer(Obj2)^ then
     Beep
 finally
   Obj1.Free;
   Obj2.Free
 end
end.


9. Какой метод будет вызван при выполнении выделенной строки -- DoVirt1 или DoVirt2? Почему?

interface

type
 TMyClass = class
   procedure DoVirt1; virtual;
   procedure DoVirt2; virtual;
 end;

implementation

procedure TMyClass.DoVirt1;
begin
end;

procedure TMyClass.DoVirt2;
begin
end;

var
 C: TMyClass;
 P: Pointer;
begin
 C := TMyClass.Create;
 try
   P := PPointer(C)^;
   P := Pointer(Longword(P) + 4);
   P := PPointer(P)^;
   asm
     MOV   EAX, C
     CALL  [P]
   end
 finally
   C.Free
 end
end.


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

10. Какое сообщение появится на экране после выполнения выделенной строки? Почему?

interface

type
 TFirstClass = class
   FInteger: Integer;
   procedure VirtMethod; virtual;
 end;

 TSecondClass = class
   FInteger: Integer;
   procedure VirtMethod; virtual;
 end;

implementation

procedure TFirstClass.VirtMethod;
begin
 ShowMessage(Format("Метод класса TFirstClass, FInteger = %d", [FInteger]))
end;

procedure TSecondClass.VirtMethod;
begin
 ShowMessage(Format("Метод класса TSecondClass, FInteger = %d", [FInteger]))
end;

var
 FirstObj: TFirstClass;
 SecondObj: TSecondClass;
 P: Pointer;
begin
 FirstObj := TFirstClass.Create;
 SecondObj := TSecondClass.Create;

 FirstObj.FInteger := 1;
 SecondObj.FInteger := 2;

 P := PPointer(FirstObj)^;
 PPointer(FirstObj)^ := PPointer(SecondObj)^;
 FirstObj.VirtMethod;
 PPointer(FirstObj)^ := P;

 FirstObj.Free;
 SecondObj.Free
end.


Вот, собственно, и все вопросы.


 
Kerk ©   (2005-08-03 19:13) [1]

Ничего так вопросы.. на brainbench"евские смахивают :)
Про class of забыл еще спросить :)


 
pasha_golub ©   (2005-08-03 19:25) [2]

Давно не обновлялся, но думаю актуальности в связи с веткой не потерял:

http://www.farata.kr.ua/testsonline/


 
TStas ©   (2005-08-03 19:27) [3]

А хорошие вопросы, ответить попробую. Так дыры в знаниях хорошо у себя выявлять.


 
Piter ©   (2005-08-03 19:28) [4]

Все не читал, но бросилось в глаза:

begin...end ©   (03.08.05 19:07)
4. Будет ли создан экземпляр класса (т.е. будет ли выделена память для него) при выполнении выделенной строки?

var
Obj: TObject;
begin
Obj.Create
end.


и какой же правильный ответ?


 
begin...end ©   (2005-08-03 19:32) [5]

> Piter ©   (03.08.05 19:28) [4]

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


 
Piter ©   (2005-08-03 19:37) [6]

begin...end ©   (03.08.05 19:32) [5]

тьфу ты. Подумалось, что написано:

TObj.Create


 
Piter ©   (2005-08-03 19:43) [7]

я бы тогда в 4-ом вопросе вырезал строчку:

>(т.е. будет ли выделена память для него)

ибо она открывает ответ и наводит на мысли о том, будет ли вызван NewInstance или нет...
Типа подсазка :)


 
Piter ©   (2005-08-03 20:09) [8]

pasha_golub ©   (03.08.05 19:25) [2]
Давно не обновлялся, но думаю актуальности в связи с веткой не потерял:

http://www.farata.kr.ua/testsonline/


блин... Сложный тест!


 
jack128 ©   (2005-08-03 20:28) [9]

begin...end ©   (03.08.05 19:07)
Что такое класс? Что такое экземпляр класса? Как работает объект?

Часто в "Основной" конференции новички (и, к сожалению, не только новички) демонстрируют частичное или полное непонимание этого.


ИМХО, для того чтобы написать грамматную программу, нужно знать лишь ответ на 3ий и 4ый вопрос. Всё остальное - жуткие техническии подробности и опираться знание этих подробностей при написании программы - как раз таки признак плохого стиля..


 
jack128 ©   (2005-08-03 20:36) [10]

jack128 ©   (03.08.05 20:28) [9]
и опираться НА знание этих подробностей


 
pasha_golub ©   (2005-08-03 20:41) [11]

Piter ©   (03.08.05 20:09) [8]
блин... Сложный тест!
Если не подколка, то рад слышать. Для того и создавался.


 
begin...end ©   (2005-08-03 20:52) [12]

> jack128 ©   (03.08.05 20:28) [9]

> ИМХО, для того чтобы написать грамматную программу,
> нужно знать лишь ответ на 3ий и 4ый вопрос.

Что ж, возможно. Спорить не буду, так как профессиональным программистом (в обоих смыслах этого слова -- а) специалистом в области программирования и б) работающим в качестве программиста) не являюсь.

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

Писать, например, код, подобный [9], в программе -- несомненно, признак плохого стиля. А вот понимать этот код (понимать то, почему он работает так, а не иначе) -- хоть и не обязательно, конечно, но всё же полезно. Тоже ИМХО.


 
Ego   (2005-08-03 21:18) [13]

Простие, не совсем в тему.Я начал изучать "Паскаль", ещё в те времена, когда водка стоила 98 рублей.У меня дома стоял БК - 01, поэтому, разумеется, основными языками для меня были "Фокал" и "Бейсик".Когда я узнал о существовании ООП, для меня это было, как для неандертальца консервная банка.Я, конечно, попытался в этом разобраться, но единственный вывод, который сделал: проблема, только в алгоритме, а всё остальное можно в книгах найти.Простите, что я всё о себе, но это мне наиболее близко.Я никогда не писал "скриптов" на "перл" - появилась задача, я придумал алгоритм, взял книжку по "перл" и "пересобачил" свои мысли в "скрипты".Конечно, я делал это гораздо дольше, чем тот человек, который общается с этим каждый день.Но, ведь, сделал.По-моему, это не тест на профессионализм, а тест на "начитку."


 
begin...end ©   (2005-08-03 21:36) [14]

> Ego   (03.08.05 21:18) [13]

> По-моему, это не тест на профессионализм, а тест на
> "начитку."

А разве кто-то говорил, что это тест на профессионализм?

Ответы на большинство предложенных вопросов можно найти, выполнив 3 действия:

1) почитав справку;
2) посмотрев исходники RTL;
3) немного подумав.

Согласитесь, что большинство вопросов начинающего программиста снимается умением пользоваться справкой и вдумчиво читать исходные тексты стандартных подпрограмм и классов Delphi. За подтверждением этого далеко ходить не надо -- достаточно зайти в "Основную".

То, что "сходу" на все вопросы ответить довольно сложно -- это совершенно естественно. Ответы на них нужно самостоятельно найти. А этого умения (и желания) новичкам зачастую и не хватает. ИМХО, конечно.


 
DiamondShark ©   (2005-08-03 21:52) [15]

Это тест на лень.


 
Piter ©   (2005-08-03 22:03) [16]

pasha_golub ©   (03.08.05 20:41) [11]
Если не подколка, то рад слышать. Для того и создавался


да какая тут подколка! То есть, лично для меня сложный

Правда, с некоторыми вопросами я не очень согласен и времени мало дается, особенно на некоторые вопросы.

Но в целом блин рулит. Занес в закладки.


 
pasha_golub ©   (2005-08-04 04:36) [17]

Piter ©   (03.08.05 22:03) [16]
Но в целом блин рулит. Занес в закладки.

Не знаю... Стоит ли. Сайт уже вот год-полтора не обновляется. Шото нету желания. :-(


 
12DFBDDh ©   (2005-08-04 07:07) [18]

ты наверное либо ЧАВО решил написать либо книгу


 
Holy ©   (2005-08-04 09:14) [19]

Интересный тест... Но мне сказали, что я его прошел...
Цитирую

Уважаемый (ая) DimON, Вы набрали 21 очков.
Результат Вашего теста лучше чем 558 результат (а, ов), имевших место до Вас.
Спасибо за прохождение теста


Что-то я не чуствую себя хоть чуток знающим Делфи, хотя и на retratech получил сертификат по Делфи5... Видимо действительно многие вопросы из этих тестов могут быть быстро решены при помощи F1...


 
jack128 ©   (2005-08-04 10:44) [20]

Holy ©   (04.08.05 9:14) [19]
Интересный тест... Но мне сказали, что я его прошел...
Цитирую

Уважаемый (ая) DimON, Вы набрали 21 очков.
Результат Вашего теста лучше чем 558 результат (а, ов), имевших место до Вас.
Спасибо за прохождение теста

Что-то я не чуствую себя хоть чуток знающим Делфи, хотя и на retratech получил сертификат по Делфи5... Видимо действительно многие вопросы из этих тестов могут быть быстро решены при помощи F1

Правельно чувствуешь. максимум ты мог набрать 50 очков, так что...


 
Rule ©   (2005-08-04 12:00) [21]

pasha_golub ©   (03.08.05 19:25) [2]
не хватает вопросов бо базам данных


 
Суслик ©   (2005-08-04 12:28) [22]

поддерживаю Jack128
технические подробности незачем использовать, знать надо, но использовать нет.

ЗЫ.
Хотя вот тут Коншин приводил пример передачи параметров в NewInstance с целью организации своего менеджера памяти для объектов.


 
Ega23 ©   (2005-08-04 12:50) [23]

2 pasha_golub ©   (03.08.05 19:25) [2]

Вопросы понравились. Только вот не сразу понял, что можно сразу несколько выриантов выбирать, и не сразу секундомер с обратным отсчётом заметил...


 
pasha_golub ©   (2005-08-04 12:54) [24]

Rule ©   (04.08.05 12:00) [21]
Создавай, вставлю. :0) Токо вот каким образом БД к Делфи привязать, кроме как TDataset не знаю.


 
Piter ©   (2005-08-04 12:55) [25]

Holy ©   (04.08.05 9:14) [19]
Видимо действительно многие вопросы из этих тестов могут быть быстро решены при помощи F1...


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


 
pasha_golub ©   (2005-08-04 13:00) [26]

Ega23 ©   (04.08.05 12:50) [23]
Вроде написано было. Там, кстати, за грубые ошибки очки снимаются.


 
Ega23 ©   (2005-08-04 13:07) [27]

Вроде написано было. Там, кстати, за грубые ошибки очки снимаются.

Значит не прочитал...


 
pasha_golub ©   (2005-08-04 13:22) [28]

Более того, даже писал, что пользоваться средой и хелпом можно и нужно.

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


 
Piter ©   (2005-08-04 14:04) [29]

pasha_golub ©   (04.08.05 13:22) [28]
а не знать на зубок дерево иерархий классов


в тоже время такие вопросы в твоем тесте встречаются :)


 
Суслик ©   (2005-08-04 14:09) [30]

что-то у меня сайт Павла Голубя тормиозит непадецки.


 
Суслик ©   (2005-08-04 14:15) [31]

Кстати, в вопросах по object pascal вопрос с absolute и set of.

Вообще говоря я не прочел (забыл) к какой версии языка это относится, но думаю, что вопрос не совсем корректный, т.к. memory managment в delphi не стандартизирован и может меняться от версии к версии. Насколько я помню в delphi2005 в хелпе раздела memory managment (т.е. как в памяти хранятся различные переменные) вообще нет. Т.е. я не очень вижу ценности знания о том, как скажем организована память под set. Я сам перестал пользоваться фактами знания физической реализации того или иного типа (пожалуй, только пользуюсь изредка знанием того, что байты в целом хранятся в обратном порядке). Хотя, конечно, ценность таких знаний сильно зависит от задачи.

PS. Прошу не кидаться обидными словами. Все сказанное - мое личное мнение.


 
Rule ©   (2005-08-04 14:32) [32]

pasha_golub ©   (04.08.05 12:54) [24]
точно такоеже отношение как и WINAPI к делфи, и если пошла уж такая жара, то давай если придираться к мелочам, то делфи - это не язык, а интегрированая среда разработки, тогда это тест по Object Pascal


 
Opilki_Inside ©   (2005-08-04 14:35) [33]

Хороший тестик, не утомляет огромным количеством вопросов и вроде все логично... Хелпами и Делфями во время его прохождения не пользовался, а таймера даже не заметил.

pasha_golub, а дата прохождения теста 2003 года стоит...


 
Opilki_Inside ©   (2005-08-04 14:39) [34]

Rule © Делфи с некоторых пор уже называется полноценным языком программирования.


 
Piter ©   (2005-08-04 14:47) [35]

Rule ©   (04.08.05 14:32) [32]
и если пошла уж такая жара, то давай если придираться к мелочам, то делфи - это не язык, а интегрированая среда разработки


с новым годом, Rule!

Borland уже давным-давно (перед выходом D7) официально переименовал Object Pascal в Delphi Language.


 
pasha_golub ©   (2005-08-04 14:49) [36]

Суслик ©   (04.08.05 14:15) [31]
А тормозит он ибо 256Кб в теории, на практике меньше, плюс дневная нагрузка на канал.

Та не в коем случае. Токмо там везде стоит packed, хотя конечно вопрос не однозначный. Как с точки зрения знаний, так и актуальности. Согласен.

Opilki_Inside ©   (04.08.05 14:35) [33]
pasha_golub, а дата прохождения теста 2003 года стоит...

У кого? Чего-то я не допонял.


 
pasha_golub ©   (2005-08-04 14:50) [37]

Суслик ©   (04.08.05 14:15) [31]
А тормозит он ибо 256Кб в теории, на практике меньше, плюс дневная нагрузка на канал.

Та не в коем случае. Токмо там везде стоит packed, хотя конечно вопрос не однозначный. Как с точки зрения знаний, так и актуальности. Согласен.

Opilki_Inside ©   (04.08.05 14:35) [33]
pasha_golub, а дата прохождения теста 2003 года стоит...

У кого? Чего-то я не допонял.


 
Ega23 ©   (2005-08-04 14:52) [38]

2 pasha_golub ©   (04.08.05 14:50) [37]
У кого? Чего-то я не допонял.

Причём, смотрю, 2 раза недопонял....  :о)


 
Суслик ©   (2005-08-04 14:55) [39]


>  [36] pasha_golub ©   (04.08.05 14:49)

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

ЗЫ.
Я видел, кто у тебя на сайте отвечал. Ув. господа, никто не оспаривает вашего знания дельфи и мастерства. Я только выразил сомнения по поводу абсолютной необходимости такого знания. Да, нужно знать, что pointer(от word) указывает не на левый байт (старший), а на правый (младший). Это вообще общая практика для всех языков программирования, где есть работа с памятьсяю. Но твердо знать, как устроен set в Delphi и полагаться на это, мне кажется рисковым.


 
pasha_golub ©   (2005-08-04 14:56) [40]

Ega23 ©   (04.08.05 14:52) [38]
Глук! :0)


 
Opilki_Inside ©   (2005-08-04 14:58) [41]

pasha_golub ©

у меня все новости на сайте за 2003 год. это правильно? и еще дата прохождения моего теста: 2003-11-18 02:59:54
хотя проходил я его 5 минут назад...


 
pasha_golub ©   (2005-08-04 14:59) [42]

Суслик ©   (04.08.05 14:55) [39]
Ты меня не понял.

Фраза "ни в коем случае" означала, что я с тобой, дорогой животный, абсолютно согласен. :0)

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


 
pasha_golub ©   (2005-08-04 15:01) [43]

Opilki_Inside ©   (04.08.05 14:58) [41]
Про новости правда. А вот про прохождение теста, это видимо у меня где-то недочет.


 
Rule ©   (2005-08-04 15:09) [44]

Opilki_Inside ©   (04.08.05 14:39) [34]
Piter ©   (04.08.05 14:47) [35]

ну и что в нем координально изменилось, кроме названия естественно ?


 
Opilki_Inside ©   (2005-08-04 15:19) [45]

Rule © Просто ты решил "придираться к мелочам" и сказал что Делфи это не язык. Так вот если уж "придираться к мелочам", то делфи это язык. А причем тут вобще его изменения? Речь ведь о мелочах идет :)


 
Rule ©   (2005-08-04 15:27) [46]

Opilki_Inside ©   (04.08.05 15:19) [45]

согласен, здаюсь ...


 
pasha_golub ©   (2005-08-04 15:30) [47]

Rule ©   (04.08.05 15:27) [46]
Приезжай в гости. Сегодня! Пока есть возможность... ;-)


 
Rule ©   (2005-08-04 15:33) [48]

pasha_golub ©   (04.08.05 15:30) [47]
сегодня не могу, сегодня мальчишник, на выходные друг жениться, а я свидетель, по этому не могу, долг :-)


 
Piter ©   (2005-08-04 15:49) [49]

Rule ©   (04.08.05 15:27) [46]
согласен, здаюсь ...


вот так бы сразу - а то сначала придрался, а потом "ну и что в неи изменилось, кроме названия?" :)))


 
pasha_golub ©   (2005-08-04 16:33) [50]

Rule ©   (04.08.05 15:33) [48]
Помощь нужна? ;0)


 
begin...end ©   (2005-08-04 17:51) [51]

> DiamondShark ©   (03.08.05 21:52) [15]

Верно. А также, возможно, на интерес к изучаемой предметной области и на способность её изучать.

> 12DFBDDh ©   (04.08.05 7:07) [18]

Вовсе нет. Да и какое я имею на это моральное право, не являясь профессиональным программистом?

> Суслик ©   (04.08.05 12:28) [22]

> технические подробности незачем использовать, знать
> надо, но использовать нет.

А чтобы их знать -- надо, как минимум, уметь пользоваться документацией. О чём и было сказано в [14].

И цель теста (по крайней мере, моего) -- вызвать "спортивный интерес" у новичков и заставить их "откопать" ответ.

Как бы там ни было, ветка ушла в сторону (как это у нас обычно и бывает), а ни одного ответа от начинающих программистов хотя бы на один вопрос из [0] пока не последовало. Возможно, они ещё будут, а возможно и нет -- может быть, тест показался совсем неинтересным или слишком сложным.

А может быть, никто из прочитавших вопросы не посчитал себя новичком? :-)

Что ж, подождём...


 
lookin ©   (2005-08-04 17:53) [52]

[51] begin...end ©   (04.08.05 17:51)
>>Что ж, подождём...

Я все равно неправильно отвечу, так что воздержусь...


 
Digitman ©   (2005-08-04 18:10) [53]


> begin...end ©   (03.08.05 19:07)  


тест, бесспорно, хорош.
проблема лишь в том, что участник его, якобы успешно прошедший и не имеющий ничерташеньки понятий о МУЛЬТИЗАДАЧНОСТИ, возьмет тест-код на вооружение ..


 
begin...end ©   (2005-08-04 18:35) [54]

> Digitman ©   (04.08.05 18:10) [53]
> ... возьмет тест-код на вооружение

О том, что такой код не надо брать на вооружение, говорилось здесь уже неоднократно. В том числе, и мной -- в [12].


 
Ptr   (2005-08-04 19:12) [55]

При ответах пользовался Delphi

1. Возникнет ли исключение при выполнении кода TObject(nil).Free? А при выполнении TObject(nil).Destroy? Почему?

Метод Free проверяет на nil указатель на экземпляр и только тогда вызывает Destroy.
При Free - исключения не будет. При Destroy - будет.

2. Возникнет ли исключение при выполнении выделенной строки в коде:

var
C: TControl;
begin
C := TControl.Create(nil);
C.Free;
C.Free
end


Возникнет. Метод Free не устанавливает ссылку на nil, для этого есть FreeAndNil

3. Если создать экземпляр этого класса и последовательно вызвать два этих метода, то они возвратят разные значения. Почему так происходит, ведь в них между begin и end написан одинаковый код?

как оказалось, в классовый метод в качестве параметра Self передается ссылка не на экземпляр класса, а на сам класс. Адрес класса и адрес экземпляра класса различаются.

Как нужно изменить код одного из методов, чтобы возвращаемые значения были одинаковыми?

например, так:

function TMyClass.Method: Integer;
begin
Result := Integer(TMyClass)
end;


4. Будет ли создан экземпляр класса (т.е. будет ли выделена память для него) при выполнении выделенной строки?

память не будет выделена, так как не будет вызван NewInstance. Зато будет вызван конструктор класса

5. Возникнет ли исключение при выполнении выделенной строки? Почему?

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

Изменится ли ситуация, если метод Method сделать виртуальным?

а если метод виртуальный, то вероятно при поиске в VMT используется конкретный экземпляр класса, а он nil.
Вообще про VMT я ничего не знаю, так, слышал, поэтому точно не представляю, но что-то типа того.

6. Какое сообщение появится на экране после выполнения выделенной строки

Ну это надо знать поадресную структуру класса.
На каком смещении от ссылки на экземпляр класса идут значения полей и т.д. Я этого не знаю. ПО-моему, действительно лишняя информация.

7. Какое сообщение появится на экране после выполнения приведённого ниже кода? Почему?

аналогично 6.

8. Чему будет равно выделенное условие -- True или False? Почему? И что в этом условии сравнивается?

а вот фиг знает.
Почему-то: PPointer(Obj1) = Pointer(Obj1)

9. Какой метод будет вызван при выполнении выделенной строки -- DoVirt1 или DoVirt2? Почему?

не знаю. Я ассемблера то не знаю. И опять эти PPointer

10. Какое сообщение появится на экране после выполнения выделенной строки? Почему?

опять эти PPointer, даже разбираться не стал, почему бы сразу не писать:

PPointer(TMyClass(Pointer(Class.Value)^).SomeMethod(PByte(LongWord(@CoolClass)+4)^))


 
begin...end ©   (2005-08-04 19:42) [56]

> Ptr   (04.08.05 19:12) [55]

Ответы на вопросы с 1-го по 4-й -- правильные. Возможно и ещё одно решение 3-го вопроса, но это неважно. Ответ на 5-й вопрос неполон.

Результат, ИМХО, очень хороший.

По крайней мере, не раз приходилось видеть, как некоторые из отвечающих (!) в "Основной" показывают незнание, например, даже 1-го или 2-го вопроса. Конечно, не забывая при этом убеждать окружающих в своей крутости.

Ждём ответов на оставшиеся вопросы. Для ответа на них тоже, в основном, достаточно того, что перечислено в [14].


 
Суслик ©   (2005-08-04 19:44) [57]

prt
Ты тут сейчас прослывешь знатоком дельфи - тебя все на работу захотят взять :)

Завтра почту починят - напишу.


 
Fay ©   (2005-08-04 20:08) [58]

2 begin...end ©   (03.08.05 19:07)
>> Тест для начинающих.
А что начинают делать люди, для которых составлен этот тест?


 
begin...end ©   (2005-08-04 20:57) [59]

> Fay ©   (04.08.05 20:08) [58]

Поскольку этот сайт называется "Мастера Delphi", то можно предположить, что под словом "начинающие" имелось в виду "начинающие программировать на Delphi". Логично, не правда ли?


 
Ptr   (2005-08-04 21:13) [60]

>Ты тут сейчас прослывешь знатоком дельфи - тебя все на работу
>захотят взять :)

да ладно... Я уверен, что очень многие знают отличие Destroy от Free.

Суслик, а вы наверняка правильно ответите на все 10 вопросов, так что какой из меня знаток...


 
pasha_golub ©   (2005-08-05 01:17) [61]

begin...end ©   (04.08.05 20:57) [59]
Начинающие Мастера Делфи...

Человек, владеющий алгоритмическим мышлением, но однако, не имевший дело с Делфи, фиг на них ответит. Ибо много архитектурных зависимостей, ИМХО.


 
12DFBDDh ©   (2005-08-05 07:32) [62]

1.1 нет
1.2 да
2 да
3 вызываются два разных обьекта self
4 нет
5 вызовет не существует обьект класса
6 честно не понял
7 адресс массива
8 сравниваются два адресса они не равны созданы два разных обьекта в памяти
9 первый метод doVirt1
10 PPointer(FirstObj)^ := PPointer(SecondObj)^;
FirstObj.VirtMethod;
метод TFirstClass.VirtMethod;

Да похоже я не мастер ((


 
Суслик ©   (2005-08-05 10:45) [63]


>  [60] Ptr   (04.08.05 21:13)


> Суслик, а вы наверняка правильно ответите на все 10 вопросов,
> так что какой из меня знаток...


Не уверен.
Если человек ответил на все, это не значит, что он умеет делать ДЕЛА.

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

ЗЫ. Напиши, кстати - у меня почту починили.


 
begin...end ©   (2005-08-05 17:20) [64]

> 12DFBDDh ©   (05.08.05 07:32) [62]

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

:-)


 
12DFBDDh ©   (2005-08-08 07:21) [65]

begin...end ©   (05.08.05 17:20) [64]
ВВВВВллллооооммммм


 
Игорь Шевченко ©   (2005-08-08 10:58) [66]

А мне вопросы понравились :)


 
begin...end ©   (2005-08-08 15:00) [67]

Поскольку на вопросы 1 - 4 уже были даны исчерпывающие ответы (см. [55]), отвечу лишь на оставшиеся.

5. Исключения здесь не возникнет, и вот почему. Во-первых, как было указано в [55], метод Method -- статический, он имеет один и тот же адрес для всех экземпляров TMyClass. Это означает, что для вычисления адреса метода не потребуется значение ссылки на объект, которая в данном случае равна nil, т.е. недействительна. Во-вторых, внутри метода такая же ситуация: метод не обращается к полям и не вызывает виртуальные или динамические методы -- а значит, ссылка на объект внутри метода тоже не понадобится. Следовательно, и исключению взяться неоткуда. Если же метод Method сделать виртуальным, то исключение будет, поскольку при вычислении адреса виртуального метода используется значение ссылки на объект (см. ответ на вопрос 9).

6. Появится сообщение "0". Переменная классового типа (когда объект создан) представляет собой указатель на область памяти, первые четыре байта которой -- это указатель на таблицу виртуальных методов (ТВМ), а оставшаяся часть области -- это поля объекта (причём поля не только данного класса, но и всех его предков, в порядке наследования). В данном случае класс TMyClass является потомком TObject, у которого нет полей. Следовательно, по смещению +4 от начала экземпляра класса находится первое поле объекта класса TMyClass. Мы получаем первый байт этого поля. Если поле типа Word равно 512, то первый (младший) байт этого поля равен 0. Возможно, более наглядно это покажет отладчик. Например, у меня он показал, что в памяти по адресу, содержащемуся в переменной C, находится следующее содержимое:

D4 79 45 00 00 02 ...

Первые 4 байта -- это ссылка на ТВМ. Она в данном случае равна $004579D4 (не забываем про принцип расположения данных в памяти -- младший байт по младшему адресу). Далее идёт значение первого поля -- первый его байт (он выделен) равен $00 (который мы и получили), а всё поле (оно же у нас двухбайтовое -- Word) равно $0200, т.е. 512.

7. Появится сообщение "456". Причины разъяснены в ответе на предыдущий вопрос. Коротко: для обращения к полю IntField компилятор прибавляет к ссылке на объект 4 -- чтобы "пропустить" указатель на ТВМ. А значит, получается указатель на второй элемент массива Arr.

8. Выделенное условие будет равно True. В этом условии сравниваются указатели на ТВМ. В данном случае у объектов Obj1 и Obj2 эти таблицы одинаковы (а значит, одинаковы и указатели на них), поскольку оба объекта являются экземплярами одного и того же класса -- TControl. Тип переменных Obj1 и Obj2 здесь значения не имеет -- важно то, что в обоих случаях был вызван конструктор одного и того же класса.

9. Будет вызван метод DoVirt2. В строке P := PPointer(C)^ получается указатель на начало ТВМ. ТВМ -- это область памяти, в которой последовательно расположены адреса виртуальных методов данного класса (включая, конечно, и виртуальные методы предков -- та же песня, что и с полями). Каждый адрес (Pointer) занимает, разумеется, 4 байта. Поскольку TMyClass является прямым потомком TObject, у которого нет виртуальных методов (не считая методов, расположенных по отрицательному смещению), то сразу получается указатель на адрес первого виртуального метода класса TMyClass -- а именно, метода DoVirt1. Кстати, ссылка на ТВМ хранится в свойстве TObject.ClassType, поэтому данную строку можно было заменить на такую: P := C.ClassType (такую же замену можно было сделать и в коде вопроса 8). Далее, в строке P := Pointer(Longword(P) + 4) получается указатель на адрес следующего метода -- DoVirt2. Наконец, в строке P := PPointer(P)^ получается сам адрес метода DoVirt2, и этот метод вызывается в строке CALL  [P]. Первую строку ассемблерной вставки (передачу Self) можно убрать в случаях, когда внутри метода нет обращения к полям и виртуальным методам (о причинах этого см. ответ на вопрос 5). Если виртуальные методы в классе TMyClass заменить на динамические, пример перестанет работать, потому что адреса динамических методов вычисляются совсем по-другому.

10. Появится сообщение "Метод класса TSecondClass, FInteger = 1". TSecondClass -- потому что в строке PPointer(FirstObj)^ := PPointer(SecondObj)^ у объекта FirstObj был заменён указатель на ТВМ. Теперь объект FirstObj пользуется ТВМ класса TSecondClass. Ему (объекту), в общем-то, пофиг, какой таблицей пользоваться. Он просто вычисляет адрес нужного метода, пользуясь имеющейся у него таблицей, и вызывает его. А то, чей это на самом деле метод -- ему по барабану. Ну а FInteger = 1 -- потому что ссылка на экземпляр TFirstClass (т.е. переменная FirstObj) не менялась, и она продолжает указывать на область памяти, в которой, в том числе, расположены поля FirstObj.

Что же надо было знать, чтобы ответить на эти вопросы?

1, 2 -- справка по TObject.Destroy. Ответ написан чёрным по белому: "Do not call Destroy directly. Call Free instead. Free verifies that the object reference is not nil before calling Destroy". Для уверенности можно было заглянуть в модуль System и посмотреть реализации Free и Destroy.

3 -- справка по Self. Открываем и читаем: "Within the implementation of a method, the identifier Self references the object in which the method is called". А ниже -- ссылка: "For information about Self in class methods, see Class methods". Переходим по ссылке и видим: "In the defining declaration of a class method, the identifier Self represents the class where the method is called". Вопрос, как говорится, "исперчен".

4 -- отладчик (CPU Window или обычная пошаговая трассировка с включённой галочкой Use Debug DCUs). Всё легко просматривается (см. [7]).

5 - 10 -- CPU Window или отладчик. Плюс знание принципа "младший байт по младшему адресу" (а ведь это -- одно из основных положений архитектуры IA-32). Структура VMT подробно описана в справке: "Предметный указатель - VMT". Там и про то, что такое VMT, и где указатель на неё, и как расположены поля -- всё написано.

Нужно было только найти. Но попытались найти всего 2 человека. Радует только то, что 2 > 0.


 
Юрий Зотов ©   (2005-08-08 15:33) [68]

> pasha_golub ©   (03.08.05 19:25) [2]

Паш, зашел, отметился в WinAPI (то ли Кот Матроскин, то ли Пес Матраскин, не помню точно). ИМХО, этот тест несложный, 50 из 50 взял влегкую, хотя к истинным знатокам системы себя отнюдь не причисляю. Полагаю, что к этому тесту надо бы добавить более сложные вопросы, чтобы оценка была более дифференцированной, а то сейчас получается, что середнячок (это, типа, такие, как я) не отличается от настоящего гуру - у обоих 50.

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

Вот такие пожелания, прими их, как конструктивную критику. А все остальное понравилось.


 
имя   (2005-08-08 15:51) [69]

Удалено модератором


 
pasha_golub ©   (2005-08-08 16:02) [70]

Юрий Зотов ©   (08.08.05 15:33) [68]
Дык, без вопросов. Но, как видишь, я на детище свое забил. Ибо кроме вопросов по самому контенту возникают еще и административные, которые меня и добили.

Кстати, если кто хочет заняться, то поделюсь ответственностью. :0)


 
begin...end ©   (2005-08-09 10:51) [71]

> pasha_golub ©   (08.08.05 16:02) [70]

Прошёл тест по API (под ником "Тупой"). 48 из 50. Присоединяюсь к пожеланию [68] по введению более сложных вопросов.


 
pasha_golub ©   (2005-08-09 11:15) [72]

begin...end ©   (09.08.05 10:51) [71]
Да, дело в том, что как усложнить вопросы в этой тематике? задавать более специфические? По каким-то конкретным функциям? Так это уже не соображаловка включается, а просто поиск по хелпам


 
Игорь Шевченко ©   (2005-08-09 11:45) [73]

begin...end ©   (09.08.05 10:51) [71]


> Присоединяюсь к пожеланию [68] по введению более сложных
> вопросов.


Па-аехали...

1. Назовите одно преимущество и один недостаток использования реестра вместо отдельных файлов ini.

2. У мыши может быть 1,2 или 3 кнопки. Используются все типа мыши. Скрывает ли эти различия уровень HAL от остальной части операционной системы. Почему да или почему нет ?

3. Уровень HAL поддерживает дату, начиная от года 1601. Приведите пример приложения, в котором это свойство полезно.

4. Подсистема POSIX нужна для реализации сигналов в стиле UNIX. Если пользователь нажмет клавишу для сигнала Quit, будет ли он планироваться как DPC или APC ?

5. В интерфейсе Win32 нет сигналов (как в Unix). Если бы сигналы были введены, они могли бы относиться к процессам, потокам, и к тем, и к другим, ни к тем, ни к другим. Выскажите свое предложение, к чему их отнести, и объясните, чем хороша ваша идея.

6. Альтернатива использования DLL заключается в том, чтобы статически компоновать каждую программу точно с теми библиотечными процедурами, к которым она обращается. Если бы нужно было внедрить эту схему, где бы это имело больший смысл, на клиентах или на серверах?

7. Файл ntdll.dll экспортирует 1179 функциональных вызовов (в Win2k), тогда как файл ntoskrnl.exe экспортирует 1209 функциональных вызовов.
Является ли это ошибкой? чем вызвано это различие?

8. Объекты, управляемые менеджеров объектов, имеют переменных размер, у различных объектов могут быть разные размеры. Может ли объект начинаться с произвольного байта в невыгружаемом пуле ?

9. Назовите три причины, по которым процесс может завершиться.

10. Вызов функции Win32 WaitForMultipleObjects позволяет потоку
блокироваться на множестве объектов синхронизации, чьи дескрипторы передаются этой функции в виде параметров. Вызывающий поток отпускается, как только один из этих объектов получает сигнал. Может ли набор объектов включать в себя два семафора, один мьютекс и одну критическую область ?

11. Допустим, что квант времени установлен равным 20 мс и что текущий  поток с приоритетом 24 только что начал свой квант. Внезапно операция вывода завершается и поток с приоритетом 28 переходит в состояние готовности. Сколько времени ему придется ждать обслуживания?

(с) Эндрю Таненбаум


 
Суслик ©   (2005-08-09 12:10) [74]


> (с) Эндрю Таненбаум

я думал ты сам, Игорь, их придумал :)))
я сходу только на 10ый могу ответить.


 
Piter ©   (2005-08-09 13:06) [75]

Игорь Шевченко ©   (09.08.05 11:45) [73]

это не по WinApi.
Это вопросы по системному программированию. Да еще со знанием технологий Unix.


 
Игорь Шевченко ©   (2005-08-09 13:17) [76]

Piter ©   (09.08.05 13:06) [75]

Это вопросы после главы "Операционная система Windows".

"Вопросы по WinAPI" без понимания того, как работает система, считаю бесполезной тратой времени.


 
Андрей Жук ©   (2005-08-09 13:31) [77]


>
> "Вопросы по WinAPI" без понимания того, как работает
> система, считаю бесполезной тратой времени.

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


 
pasha_golub ©   (2005-08-09 13:36) [78]

Игорь Шевченко ©   (09.08.05 11:45) [73]
Ого... Круто! А можно ответы на эти вопросы увидеть?


 
Суслик ©   (2005-08-09 13:37) [79]

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


 
Игорь Шевченко ©   (2005-08-09 13:42) [80]

pasha_golub ©   (09.08.05 13:36) [78]

Ответы Таненбаум не приводит :)


 
pasha_golub ©   (2005-08-09 13:45) [81]

Игорь Шевченко ©   (09.08.05 13:42) [80]
Ну, я, если честно, на Таненбаума и не надеялся. Я думал, ты расскажешь. :)


 
Игорь Шевченко ©   (2005-08-09 13:50) [82]

pasha_golub ©   (09.08.05 13:45) [81]

Ты полагаешь, я могу правильно ответить на все вопросы ? :) Ошибаешься :)


 
Piter ©   (2005-08-09 14:14) [83]

Игорь Шевченко ©   (09.08.05 13:17) [76]
"Вопросы по WinAPI" без понимания того, как работает система, считаю бесполезной тратой времени


вот Андрей в [77] хорошо написал. Что мне мешает водить машину, если я не знаю внутреннего устройства двигателя?

Оно, конечно, знать неплохо, но вовсе не обязательно. Как считаете?


 
Суслик ©   (2005-08-09 14:20) [84]


> Оно, конечно, знать неплохо, но вовсе не обязательно. Как
> считаете?


Совершенно не обязательно, но полезно, т.к. может (или нет) открыть новые перспективы.


 
Юрий Зотов ©   (2005-08-09 14:20) [85]

> Piter ©   (09.08.05 14:14) [83]

> Оно, конечно, знать неплохо, но вовсе не обязательно.

А никто и не заставляет. Просто будет уже не 50 баллов, а меньше. А 50 получат те, кто знает. Вот и будет видно, кто - водитель, кто - водила, а кто - ездила. В чем, собственно, цель теста и состоит.


 
Андрей Жук ©   (2005-08-09 14:24) [86]

Юр, а вы БД проектировали?
Если это опенсорсная разработка - то вы еще можете посмотреть исходники. И то, даже если это простенький Firebird, там исходников на 40 Мб.
А если это Oracle или MSSQL?
Сокрытие данных - оно не только в ОО программировании нужно.
Не пытайся объять необъятное.


 
jack128 ©   (2005-08-09 14:33) [87]

Суслик ©   (09.08.05 12:10) [74]
я думал ты сам, Игорь, их придумал :)))
я сходу только на 10ый могу ответить.


А на 9ый ??


 
Суслик ©   (2005-08-09 14:44) [88]


> [87] jack128 ©   (09.08.05 14:33)
> А на 9ый ??


Ну это надо смотреть, я так не помню:

1. закончился последний поток процесса
2. terminateprocess
3. exitprocess
4. необработанное исключение

вроде все, только почему-то уже 4. :))

но я смотрел, т.к. не помню exitprocess или processexit.

может еще что?


 
Piter ©   (2005-08-09 14:53) [89]

Суслик ©   (09.08.05 14:44) [88]
закончился последний поток процесса


хм. По-моему, если закончился ОСНОВНОЙ ПОТОК процесса

Суслик ©   (09.08.05 14:44) [88]
необработанное исключение


Это как? О каком исключении ты говоришь?


 
Суслик ©   (2005-08-09 14:57) [90]


>  [89] Piter ©   (09.08.05 14:53)


> хм. По-моему, если закончился ОСНОВНОЙ ПОТОК процесса

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


> Это как? О каком исключении ты говоришь?

если в приложении (в одном из потоков) есть необработанное исключение, то приложение снимается системой. Это я в рихтере видел. Сейчас лень идти искать. Но там, где про потоки и контексты потоков говорится.


 
Piter ©   (2005-08-09 15:18) [91]

Суслик ©   (09.08.05 14:57) [90]
если в приложении (в одном из потоков) есть необработанное исключение, то приложение снимается системой


Да не... Ну как такое может быть? Может, поток там снимается?


 
Суслик ©   (2005-08-09 15:26) [92]


>  [91] Piter ©   (09.08.05 15:18)

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


 
Суслик ©   (2005-08-09 15:26) [93]

И вообще - сейчас прийдет кто-то знающий, навешает на нас значков и может прояснить ситуацию :)


 
jack128 ©   (2005-08-09 15:27) [94]

Суслик ©   (09.08.05 14:44) [88]
4. необработанное исключение


Исключения ВСЕГДА обрабатываются.. Если их не обработала программа, то исключение обработает система.  Стандартный обработчик -это всего лишь вызов ExitProcess, так что вот и получается, что вариантов всего три..
Суслик ©   (09.08.05 14:57) [90]
может и так, я уже подзабыл - как прочел с тех пор это знание не пригождалось.

нет, не так. Должны закончится ВСЕ потоки процесса.

Piter ©   (09.08.05 15:18) [91]
Да не... Ну как такое может быть? Может, поток там снимается?

Легко проверить

program Project1;

{$APPTYPE CONSOLE}

uses
 SysUtils, Windows;

function ThreadProc(Param: Pointer): Integer;
begin
 Sleep(1000);
 raise Exception.Create("Test");
end;
var
 Dummy: THandle;
begin
 CloseHandle(BeginThread(nil, 0, ThreadProc, nil, 0, Dummy));
 ReadLn;
end.


 
Суслик ©   (2005-08-09 15:47) [95]


> [94] jack128 ©   (09.08.05 15:27)


> нет, не так. Должны закончится ВСЕ потоки процесса.

значит изначально прав был.

А по поводу необработанных исключений, думаю надо почитать, т.к. память мне говорит иное.


 
jack128 ©   (2005-08-09 15:59) [96]

Суслик ©   (09.08.05 15:47) [95]
> нет, не так. Должны закончится ВСЕ потоки процесса.

значит изначально прав был.

Кстати говоря, доказать не совсем просто, дело в том, что RTL при завершении основного потока принудительно вызывает ExitProcess, так что для док-ва нужен примерно такой код:

program Project1;
uses
 SysUtils, Windows;

function OpenThread(
 dwDesiredAccess: DWORD;
 bInheritHandle: BOOL;
 dwThreadId: DWORD
): THandle; stdcall; external "kernel32.dll" name "OpenThread";

const
 THREAD_TERMINATE  = $0001;

function ThreadProc(Param: Pointer): Integer;
var
 h: THandle;
begin
 h := OpenThread(THREAD_TERMINATE, False, MainThreadId);
 if h = 0 then
   raise Exception.Create("ХАНА");
 if not TerminateThread(h, 0) then
   RaiseLastWin32Error;
 Sleep(10000);
end;

var
 Dummy: THandle;
 h: THandle;
begin
 CloseHandle(BeginThread(nil, 0, ThreadProc, nil, 0, Dummy));
 Sleep(100); // ждем пока дополнительный поток начнет работу..
end.


 
Суслик ©   (2005-08-09 16:04) [97]


>  [96] jack128 ©   (09.08.05 15:59)

под win надо доказывать на vc++ 6. imho.

В дельфе главную функцию (ту, которая еще главнее main) фиг подменишь.


 
GuAV ©   (2005-08-09 16:27) [98]


jack128 ©   (09.08.05 15:27) [94]

> нет, не так. Должны закончится ВСЕ потоки процесса.


Всегда думал иначе, решил проверить.
Оказывается, приложение таки остаётся работать с другими потоками, однако IDE реагирует так, будто приложение полностью завершило работу. Странно.


 
GuAV ©   (2005-08-09 16:29) [99]

program thdtest;

uses
 Windows;

function SleepThd(Parameter: Pointer): Integer;
begin
 Sleep(DWORD(Parameter));
end;

var ID: DWORD;
begin
 CloseHandle(BeginThread(nil, 0, SleepThd, Pointer(4000), 0, ID));
 ExitThread(0);
end.


IDE включает дизайнеры сразу, однако приложение 4 сек болтается в процессахю


 
jack128 ©   (2005-08-09 18:11) [100]

GuAV ©   (09.08.05 16:29) [99]
IDE включает дизайнеры сразу, однако приложение 4 сек болтается в процессахю

Что значит "включает дизайнеры" ??   В семерке кнопка Run 4 секунды заблокированна, как и положенно.. А про exitthread я чего то не подумал..


 
jack128 ©   (2005-08-09 18:12) [101]

GuAV ©   (09.08.05 16:27) [98]
Всегда думал иначе, решил проверить.

А я тоже так всегда думал..   И очень многие так думают, потому что
jack128 ©   (09.08.05 15:59) [96]
RTL при завершении основного потока принудительно вызывает ExitProcess


 
GuAV ©   (2005-08-09 19:11) [102]

jack128 ©   (09.08.05 18:11) [100]
Что значит "включает дизайнеры" ??   В семерке кнопка Run 4 секунды заблокированна, как и положенно..


У меня нет, сразу нажимается повторно.
"дизайнеры" - Object TreeView, Object Inspector.

build 7.0.4.453


 
Eraser ©   (2005-08-09 19:38) [103]

Завершение процесса
Процесс можно завершить четырьмя способами:

входная функция первичного потока возвращает управление (рекомендуемый способ);
один из потоков процесса вызывает функцию ExitProcess (нежелательный способ);
поток другого процесса вызывает функцию TerminateProcess (тоже нежелательно);
все потоки процесса умирают по своей воле (большая редкость).
В этом разделе мы обсудим только что перечисленные способы завершения процесса, а также рассмотрим, что на самом деле происходит в момент его окончания.

(C) Джеффри РИХТЕР


 
GuAV ©   (2005-08-09 19:50) [104]


> входная функция первичного потока возвращает
> управление (рекомендуемый способ);


Вот только что разобрались, что этот способ сводится к

> один из потоков процесса вызывает функцию ExitProcess
> (нежелательный способ);


Что насчёт рекомендуемый/нежелательный, скорее всего имеется ввиду что при ExitProcess (в отличии, кстати, от Halt)не выполнятся финализации модулей (и код после ExitProcess, который тоже может содержать важный код заваершения).

Джеффри РИХТЕР писал про MS С++, а про на Delphi, но я не думаю что есть принципиальные для этой темы отличия.


 
Eraser ©   (2005-08-09 19:57) [105]

GuAV ©   (09.08.05 19:50) [104]
но я не думаю что есть принципиальные для этой темы отличия.


Согласен.


 
GuAV ©   (2005-08-09 20:10) [106]

Есть идея как точно проверить, вызывается ли ExitProcess кодом в ехе файле, выполняемым после end. Достаточно в своей таблице импорта перебить ExitProcess на ExitThread. Затем создать доп. поток, в нём задержку, или окно, а в основном дойти до end. . Если случай "входная функция первичного потока возвращает управление" - отдельный и [89] верно, то приложение должно завершится при end. , иначе - остаться работать до завершения доп. потока.


 
GuAV ©   (2005-08-09 20:18) [107]

Eraser ©   (09.08.05 19:38) [103]

Там же ниже, кстати, написано, что в первом (рекомендуемом) способе ExitProcess будет вызванна кодом рантайм библиотеки С/С++ (в нашем случае Delphi).


 
Eraser ©   (2005-08-09 20:25) [108]

GuAV ©   (09.08.05 20:18) [107]

Точно
Кстати, в документации из Platform SDK утверждается, что процесс не завершается до тех пор, пока не завершится выполнение всех его потоков. Это, конечно, верно, но тут есть одна тонкость. Стартовый код из библиотеки С/С++ обеспечивает завершение процесса, вызывая ExitProcess после того, как первичный поток Вашего приложения возвращается из входной функции. Однако, вызвав из нее функцию ExitThread (вместо того чтобы вызвать ExitProcess или просто вернуть управление), Вы завершите первичный поток, но не сам процесс — если в нем еще выполняется какой-то другой поток (или потоки).

соответсвенно 1 это просто следствие. RTL за-нас делает код правильным.


 
jack128 ©   (2005-08-09 21:48) [109]

GuAV ©   (09.08.05 20:10) [106]
Есть идея как точно проверить, вызывается ли ExitProcess кодом в ехе файле, выполняемым после end.

вообще говоря достаточно воспользоваться hot-key"ем из из твоей анкеты ;)


 
Игорь Шевченко ©   (2005-08-10 09:48) [110]

Eraser ©   (09.08.05 19:38) [103]


> входная функция первичного потока возвращает управление
> (рекомендуемый способ);


> все потоки процесса умирают по своей воле (большая редкость).
>


И чем это, собственно, отличается ?


 
Думкин ©   (2005-08-10 10:50) [111]


> [110] Игорь Шевченко ©   (10.08.05 09:48)
> Eraser ©   (09.08.05 19:38) [103]

Ну, типа в 10-ку. А чем?


 
GuAV ©   (2005-08-10 14:01) [112]

Игорь Шевченко ©   (10.08.05 9:48) [110]

> > входная функция первичного потока возвращает
>управление
>> (рекомендуемый способ);
>
>
> > все потоки процесса умирают по своей воле (большая
>редкость).
>>
>
>
> И чем это, собственно, отличается ?


Вызываемой функцией ExitProcess в первом / ExitThread во втором случае. Возможным наличием других "неявно завершенных" потоков в первом случае. Нет ?

Хотя, если бы не было вызова ExitProcess в коде RTL после end. , то, наверное ничем бы эти способы не отличались.


 
Игорь Шевченко ©   (2005-08-10 14:20) [113]


> Вызываемой функцией ExitProcess в первом / ExitThread во
> втором случае


Я полагаю, что завершение процесса происходит вне зависимости от наличия RTL :)


 
GuAV ©   (2005-08-10 17:02) [114]

Игорь Шевченко ©   (10.08.05 14:20) [113]

>Я полагаю, что завершение процесса происходит вне зависимости от наличия RTL :)

IMHO, неверно.

Отдельный тест на asm показал, что когда первичный поток возвращает управление, а другой поток ещё нет, работа другого потока не прекращается.

.386
locals
jumps
.model flat,STDCALL

extrn            CreateThread:PROC
extrn            ExitProcess:PROC
extrn            ExitThread:PROC
extrn            GetModuleHandleA:PROC
extrn            MessageBoxA:PROC

GetModuleHandle  equ <GetModuleHandleA>
MessageBox       equ <MessageBoxA>

.data

hInst              dd 0
ThdID              dd 0

szTitleName        db "Win32 Assembly Program", 0
szPrimaryThread    db "Click ok to exit primary thread",0
szSecThread        db "Click ok to exit secondary thread",0

;-----------------------------------------------------------------------------

.code

thread:

       push    0
       push    OFFSET szTitleName
       push    OFFSET szSecThread
       push    0
       call    MessageBox

       ; push    0
       ; call    ExitThread

       ret 4

start:

       push    0
       call    GetModuleHandle         ; get hmod (in eax)
       mov     [hInst], eax            

       push    OFFSET ThdID            ; pointer to returned thread identifier
       push    0                       ; creation flags
       push    0                       ; argument for new thread
       push    OFFSET thread           ; pointer to thread function
       push    0                       ; initial thread stack size, in bytes
       push    0                       ; pointer to thread security attributes  
       call    CreateThread

       push    0
       push    OFFSET szTitleName
       push    OFFSET szPrimaryThread
       push    0
       call    MessageBox
       
       ; push    0
       ; call    ExitProcess

       ret

ends
end start


Процесс будет завершен только тогда, когда будут закрыты оба messagebox.


 
Игорь Шевченко ©   (2005-08-10 17:12) [115]

GuAV ©   (10.08.05 17:02) [114]


> Отдельный тест на asm показал, что когда первичный поток
> возвращает управление, а другой поток ещё нет, работа другого
> потока не прекращается.


Так с этим никто не спорит вроде.

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


 
Суслик ©   (2005-08-10 17:58) [116]


>  [115] Игорь Шевченко ©   (10.08.05 17:12)
> GuAV ©   (10.08.05 17:02) [114]
>
> Пожтому и остаются три способа - возврат управления всеми
> потоками, вызов ExitProcess и вызов TerminateProcess.
> Так вроде получается.


я все-таки думаю, что предложенный мной 4й способ (необработанное исключение в одном из потоков), представляет также верный ответ.


 
Игорь Шевченко ©   (2005-08-10 18:13) [117]

Суслик ©   (10.08.05 17:58) [116]

Необработанное исключение в одном из потоков приводит к вызову системной функции UnhandledExceptionFilter, после чего вызывается функция ExitProcess.


 
Суслик ©   (2005-08-10 18:26) [118]


>  [117] Игорь Шевченко ©   (10.08.05 18:13)

А почему ты уверен, что в действительности ExitProcess не вызывает TerminateProcess или наоборот?


 
GuAV ©   (2005-08-10 18:34) [119]

Суслик ©   (10.08.05 17:58) [116]
RaiseException + F1:

...

Remarks

...

Raising an exception causes the exception dispatcher to go through the following search for an exception handler:

1. The system first attempts to notify the process"s debugger, if any.
2. If the process is not being debugged, or if the associated debugger does not handle the exception, the system attempts to locate a frame-based exception handler by searching the stack frames of the thread in which the exception occurred. The system searches the current stack frame first, then proceeds backward through preceding stack frames.
3. If no frame-based handler can be found, or no frame-based handler handles the exception, the system makes a second attempt to notify the process"s debugger.
4. If the process is not being debugged, or if the associated debugger does not handle the exception, the system provides default handling based on the exception type. For most exceptions, the default action is to call the ExitProcess function.


Итого, процесс можно завершить тремя способами:

1. Завершение всех потоков
потоки м.б. завершены возвратом потоковой функции или вызовом ExitThread.

2. вызов ExitProcess
ExitProcess м.б. вызванна непосредственно, возвратом из кода программы (достижением end. в Delphi, возвратом из main/WinMain/etc в C ...), стандартной обработкой исключения.

3. вызов TerminateProcess


 
Игорь Шевченко ©   (2005-08-10 18:36) [120]

Суслик ©   (10.08.05 18:26) [118]

Вообще-то обе они оканчиваются на NtTerminateProcess...


 
Суслик ©   (2005-08-10 18:37) [121]


>  [119] GuAV ©   (10.08.05 18:34)

ладно, согласен, убедил :)


 
Суслик ©   (2005-08-10 18:37) [122]


>  [120] Игорь Шевченко ©   (10.08.05 18:36)
> Суслик ©   (10.08.05 18:26) [118]
>
> Вообще-то обе они оканчиваются на NtTerminateProcess...


Вот я и хочу сказать, что причин то может быть и не 3 а 2? :)


 
Игорь Шевченко ©   (2005-08-10 18:38) [123]

Суслик ©   (10.08.05 18:37) [122]

С точки зрения пользователя - три. С точки зрения системы - одна.


 
GuAV ©   (2005-08-10 20:22) [124]

Обсудим другие вопросы.


> 1. Назовите одно преимущество и один недостаток
> использования реестра вместо отдельных файлов ini.


Думал такой вариант: реестр хранит настройки централизовано для ОС (отсюда отсуствие вопросов про возможность запись настроек, гарантированая работа восстаонвления системы), ini - приложение хранится централизовано с точки зрения файловой системы (м.б. заархиивировано вместе с настройками, перенесено на другую машину с ними, сохранить настройки при переустаовке ОС). Однако ini файлы можно хранить в CSIDL_APPDATA ...


> 6. Альтернатива использования DLL заключается в том,
> чтобы статически компоновать каждую программу точно с
> теми библиотечными процедурами, к которым она
> обращается. Если бы нужно было внедрить эту схему, где
> бы это имело больший смысл, на клиентах или на
> серверах?


При одновременном использовании одной DLL несколькими приложениями, если её удалось загрузить по одинаковому адресу в каждом, и код DLL не был изменён после загрузки, то различным копиям кода DLL в виртуальных адресных пространствах процесса сответствует не более одной копии в физической памяти.
С другой стороны, при запуске только одного приложения в его АП будет спроецирована вся dll вместе с нужными и не нужными подпрограммами. При этом, возможно, когда часть ненужных функций не будет загруженна в физическую память, другая их часть попадёт на те же страницы что и нужные.
Вывод использования DLL приведёт к "экономии" физической памяти в случае одновременной работы различных приложений, использующих функции DLL. И к "перерасходу", если только одно приложение работает.
Предложенную схему, IMHO, больший смысл внедрять на клиентах.



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

Текущий архив: 2005.09.04;
Скачать: CL | DM;

Наверх




Память: 0.89 MB
Время: 0.058 c
1-1123737620
Гриха
2005-08-11 09:20
2005.09.04
JPEG и фоновый рисунок рабочего стола


2-1067014118
овен
2003-10-24 20:48
2005.09.04
компоненты


3-1122357721
evvcom
2005-07-26 10:02
2005.09.04
Отключение триггеров в Оракл


5-1095963566
Igor_
2004-09-23 22:19
2005.09.04
Обработчик событий OnKeyPress


3-1121748027
emo
2005-07-19 08:40
2005.09.04
ODBC+login