Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > Delphi: Общие вопросы > исключение AV в качестве уведомления


Автор: MetalFan 31.5.2007, 22:47
как известно, исключения в Делфи могут носить уведомительный характер и обрабатываться в "вышестоящих" процедурах или методах.
но на сколько оправдано использование исключения, генерируемого в случае нарушения доступа к памяти
для проверки на корректность указателя на экземпляр класса?

вот пример кода:

Код

type
   TSomeClass = class
...
    procedure  SomeMethod;
...
  end;
  
  var
    gSomeClassInstance: TSomeClass;
...
implementation
  procedure TSomeClass.SomeMethod;
  begin
    ....
  end;

  procedure TEST;
  begin
    try
       gSomeClassInstance.SomeMethod;
    except //АГА! наверное он не создан!
      gSomeClassInstance := TSomeClass.Create;
      gSomeClassInstance.SomeMethod;
      if SomeCondition then
        gSomeClassInstance.Free;
    end;
  end; 


вот примерно такой метод был предложен одним из участников форума для
"отслеживания" созданности формы... только вместо TSomeClass.SomeMethod другой класс и метод соотв. использовался.

так предлагаю обсудить все плюсы и минуся такого подхода.
от себя скажу одно: я считаю, что так писать НЕДОПУСТИМО smile. и точка.
голосоуем, высказываемся) 

Автор: Snowy 31.5.2007, 23:22
Вопрос некорректный.
Ибо ответ - да. Возможено.
Но не стоит.
Я бы даже сказал - моветон.
Максимум - ассерты, не включаемые в релиз.
Исключения должны использоваться по назначению.
Например в случаях обращения к железу или сети.
То есть там, где мы не гарантируем однозначность исхода.
Также порождение исключений имеет смысл в библиотеках, при несоблюдении правил обращения.
Но строить на нах логику - дурной тон.
Отладка таких приложений - сплошной геморрой.

Автор: MetalFan 31.5.2007, 23:47
Цитата(Snowy @  31.5.2007,  23:22 Найти цитируемый пост)
Вопрос некорректный.
Ибо ответ - да. Возможено.
Но не стоит.
Я бы даже сказал - моветон.
Максимум - ассерты, не включаемые в релиз.
Исключения должны использоваться по назначению.

"самодельные" исключения - может и да.
но никак не AV...

Автор: aktuba 1.6.2007, 00:51
Получение AV уже само по себе плохо. А использование любого AV в логике программы - я думаю, как минимум, грубая ошибка. Представляю, каково будет людям, которые потом будут читать подобный код и пытаться отладить  smile 

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

Автор: Snowy 1.6.2007, 01:14
Под исключениями я понимал try, отловленные AV, raise.
А что касается сознательных AV, то я вообще не вижу места для их применения.
Их просто не должно быть в коде.

Автор: aktuba 1.6.2007, 08:12
Цитата

Под исключениями я понимал try, отловленные AV, raise.
А что касается сознательных AV, то я вообще не вижу места для их применения.
Их просто не должно быть в коде. 


Во-во!!! И я про то же!!! smile 

Автор: MetalFan 1.6.2007, 15:27
Цитата(Snowy @  1.6.2007,  01:14 Найти цитируемый пост)
А что касается сознательных AV, то я вообще не вижу места для их применения.

именно про сознательные AV я имел ввиду)

Автор: ama_kid 1.6.2007, 16:06
MetalFan, я поставил ответ "Да" только потому, что вопрос действительно, как сказал Snowy, не совсем некорректен и я это знаю на 100% ибо применяю. Если бы вопрос звучал "Корректно ли использовать AV..." - тогда бы я промолчал, ибо действительно не знаю...
Но что мы получили в итоге? Пока мы получили только де-факто материал для новой "религиозной войны", не более того. В моем топике ты мне написал хороший ответ, не спорю, но опять же - давай по порядку?
Цитата
 AFAIK в случае возникновения нарушение доступа в драйвере система уходит в bsod...
В каком драйвере? BSOD - это и есть "AV" драйвера... А тот AV, который мы обсуждаем - это де-факто есть "обычная нотификация" системной библиотеки менеджера памяти о запрете на использование запрошенного участка... Каким местом я в данном случае работаю с драйвером? И вообще, если честно, я не совсем понял как ты прицепил к данной проблеме тему драйверов...
Цитата
или в след.версии делфи что-то поменяется в методе ShowModal и твое приложение попросту откажется нормально работать...
Неужто данный класс AV зависит от ребят из Борланда?
Цитата
а что, если часть методов "умершего" экземпляра класса отработает, "успешно" поназапишет чего-нибудь в те части памяти, что используются уже другими экземплярами... и в самом конце вдруг все-таки свалится с AV. ты радостно создаешь новую форму в except блоке... но вдруг у тебя начинают невзначай подглючивать другие формы/классы... или все будет в шоколаде, а приложение у клиента начнет валиться? а?
Вот... Вот именно этого я и хотел бы добиться... Я в обязательном порядке поставлю плюс (и может быть даже не один) тому человеку, который кинет в меня приложением (на дельфи, ессно), использующим мой подход, у которого будут проявляться описанные тобой симптомы - ведь это могло бы меня многому научить... smile

Snowy
Цитата(Snowy @  1.6.2007,  01:14 Найти цитируемый пост)
Их просто не должно быть в коде.
При всем к тебе уважении, чем обосновано такое утверждение? Конкретным примером? Или просто принципиальным неиспользованием? Я, например, про оператор goto тоже много аналогичного слышал, и хотя согласен с таким утверждением и после школьных времен сам никогда не использую, но тем не менее никогда не скажу вслух категоричного "нет", ибо знаю границы его применения и могу допустить возможность его использования. Ну и (если честно) не очень люблю "табу" в программировании...

P.S.  В общем, пока я в растерянности... С одной стороны - все вокруг говорят, что подчинение AV своим нуждам - это моветон, это недопустимо, это грубейшая ошибка, но с другой стороны:
1) пока никто не предоставил убедительного доказательства ошибочности использования такого подхода... 
2) голые теории пока меня не убеждают (тем более, что в принципе эти все доводы я и сам прекрасно понимаю)...
3) И самое главное - уже довольно продолжительное время я использую этот подход при 0% некорректной отработке...  Все, кому довелось сопровождать мой код - не раз говорили мне о чистоте и логичности моего кода (не в качестве хвастовства, а для ответа на "Отладка таких приложений - сплошной геморрой" и "Представляю, каково будет людям, которые потом будут читать подобный код и пытаться отладить"). Неужели они все притворялись? Пойду выпью йаду...

Автор: Rennigth 1.6.2007, 16:21
ama_kid, 
Не буду повторять слова других участников этого топика и двух других связанных, но скажу что ответил Нет вопросе и тож считаю такой подход неприемлимым.

P.S. А тебе самому не надоело во время отладки ловить эксептионы и нажимать каждый раз OK+F9?

Добавлено через 5 минут и 59 секунд
ama_kid, 
Кстати, а чем тебе не нравиться подход например вот такой:

Код

  TSomeForm.CloseForm(Sender: TObject; Action: TCloseAction);
  begin
    Action := caFree;
    fmSomeForm := nil;
  end;


При вызове:
Код

  if not Assigned(fmSomeForm) then
    fmSomeForm := TSomeForm.Create(nil);
  fmSomeForm.Show;
  //...


Или я контекст упустил уже  smile

Автор: Snowy 1.6.2007, 16:31
Никто не запрещает использовать данный приём.
Просто есть некоторые критерии, по которым характеризуется качество кода.
Тот же goto сильно ухудшает понимание логики кода.
В коде должна быть логичность и красота. Это ж искусство smile

Автор: pseud 1.6.2007, 16:40
ama_kid, вспомним твой код.
Код

  try
    fmOptions.ShowModal;  
  except
    fmOptions:=TfmOptions.Create(nil);
    fmOptions.ShowModal;
  end;


Пофантазируем. 
1)-------------

Допустим у формы fmOptions есть несколько конструкторов.
CreateFull(AOwner: TComponent); - создаем форму со всеми контролами видимыми.
CreateGeneral(AOwner: TComponent); - создаем форму только с основными контролами видимыми.
Create(AOwner: TComponent; AParam: Integer); reintroduce; - создаем форму еще через какой-то кавардак.

Далее. 
2)-------------

Раз ты вызываешь метод ShowModal, значит ты предполагаешь, что форма ранее была создана, но не удалена.
А если она была создана первым конструктором.
А ты бы хотел создать ее 2м конструктором.
Наверно тогда ты заюзаешь конструкцию:
Код

fmOptions := TfmOptions.Конструктор;
try
  fmOptions.ShowModal;
finally
  fmOptions;
end;


В итоге в коде твоей проги будет намешан салат из разных методов создания/открытия форм.

3)-------------

Мне кажется что гораздо логичнее (если ты подозреваешь что форма уже создана) сделать так:

Код

FreeAndNil(fmOptions);
fmOptions := TfmOptions.Конструктор;
try
  fmOptions.ShowModal;
finally
  fmOptions;
end;


а может так:

Код

if fmOptions <> nil then
  FreeAndNil(fmOptions);
if fmOptions <> nil then
  raise Exception.Create('Ругань');
fmOptions := TfmOptions.Конструктор;
try
  fmOptions.ShowModal;
finally
  fmOptions;
end;




Автор: aktuba 1.6.2007, 16:45
Цитата

пока никто не предоставил убедительного доказательства ошибочности использования такого подхода... 


А какое тебе надо доказательство - написать код, который будет валить одни AV??? Извени, но я привык к обратному и вряд ли смогу подобное организовать.

Цитата

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


Если сам понимаешь, как же они тебя не убеждают? Какая-то не понятная, для меня, логика...

Цитата

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


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

Автор: ama_kid 1.6.2007, 17:03
Цитата(Rennigth @  1.6.2007,  16:21 Найти цитируемый пост)
P.S. А тебе самому не надоело во время отладки ловить эксептионы и нажимать каждый раз OK+F9?
Нет, не надоело, потому что "Stop on Delphi exceptions" у меня отключен smile

Цитата(Rennigth @  1.6.2007,  16:21 Найти цитируемый пост)
чем тебе не нравиться подход например вот такой
Вот к примеру этим:
Код
 fmSomeForm:=@SomeVariable;
  ...
  if not Assigned(fmSomeForm) then // fmSomeForm - Assigned
    fmSomeForm := TSomeForm.Create(nil);
  fmSomeForm.Show; // БАЦ!


Цитата(pseud @  1.6.2007,  16:40 Найти цитируемый пост)
А если она была создана первым конструктором.А ты бы хотел создать ее 2м конструктором.
Ситуация, не лишенная права на жизнь, но я такого не применяю. К тому же это достаточно легко обходится... Ну и я никогда не говорил, что не обнуляю указатель на объект формы... В любом случае, анализ интересен...

Цитата(aktuba @  1.6.2007,  16:45 Найти цитируемый пост)
Если сам понимаешь, как же они тебя не убеждают? Какая-то не понятная, для меня, логика...
Логика в том, что я их понимаю, но они не заставляют меня однозначно отказаться в их пользу...

Цитата(Snowy @  1.6.2007,  16:31 Найти цитируемый пост)
В коде должна быть логичность и красота. Это ж искусство
Конечно, согласен! Но... понятие красоты - для каждого своё, и я не возьмусь судить красоту в чьем-то понимании только потому, что оно не совпадает с моим, более того, я всегда постараюсь её понять... Блин, ушел во флейм... Ладно, всем спасибо за интересные мнения, ушел домой обдумывать...

Автор: Rennigth 1.6.2007, 17:08
Цитата(pseud @  1.6.2007,  16:40 Найти цитируемый пост)
if fmOptions <> nil then
  FreeAndNil(fmOptions);


А ты думаешь это не может вызвать исключения?  smile 

Указатель-то жыв еще может быть. Ты в суть проблеммы не вник. 
ama_kid, Ползуется своим способом чтобы всегда быть уверенным чтобы быть уверенным что
ничего криминального не случиться. Просто его подход к проблеме немного всех удивил.

Добавлено через 45 секунд
 smile  О чет я опоздал... курить хотел. Написал а не отправил.

Добавлено через 3 минуты и 22 секунды
Цитата(ama_kid @  1.6.2007,  17:03 Найти цитируемый пост)
fmSomeForm:=@SomeVariable;

А зачем глобальный указатель переназначать!!!? 
А если ты в CloseForm всегда будешь ее разрушать и обнулять ее указатель то все будет нормально.

Автор: pseud 1.6.2007, 17:16
Цитата(aktuba @  1.6.2007,  16:45 Найти цитируемый пост)
если автомобиль врезался, подкачаем колесо, если не врезался - доедем так... 


aktuba, прав.

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

Например создаю 2 формы с кнопкой в каждой
и пишу код в одной форме
Код

procedure TForm1.Button1Click(Sender: TObject);
begin
  Form2.ShowModal;
end;

во второй
Код

try
  Form1.ShowModal;
except
  Form1 := TForm1.Create(Self);
  Form1.ShowModal;
end;


ama_kid, 
Да действительно ShowModal вызовет Exception.
Цитата

Project Project1.exe raised exception class EInvalidOperation with message 'Cannot make a visible window modal'. Process stopped. Use Step or Run to continue.

Но не из-за отсутствия Form1. 
А из-за того что она уже лежит под модальной формой Form2.

Да код отработает но на экране будет пирог (причем очень не сладкий)
1. TForm1, на которую уже нет указателя (мы его отдали, см.п.3).
2. Form2: TForm2;
3. Form1: TForm1;

Добавлено через 8 минут
Цитата(Rennigth @  1.6.2007,  17:08 Найти цитируемый пост)
Указатель-то жыв еще может быть


Rennigth, а помоему ни капельки не жив:
Pointer(Obj) := nil;

Код

procedure FreeAndNil(var Obj);
var
  Temp: TObject;
begin
  Temp := TObject(Obj);
  Pointer(Obj) := nil;
  Temp.Free;
end;


Автор: Rennigth 1.6.2007, 17:38
pseud, 
Не правильно выразился. Он может иметь указатель(т.е. не nil), но уже на несуществующий объект. 

P.S. Из-за этого в приципе дискусия и началась smile

Автор: dumb 1.6.2007, 17:50
вообще, тут речь идет скорее о надежности кода, а не о красоте, логичности итд.

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

поэтому тут можно говорить о умышленном допущении, основанном на малой вероятности возникновения вышеописанной ситуации. тем более обсуждается не серверная часть, работающая в режиме 24*7, а всего лишь GUI. в общем же случае, таких методов imho стоит таки избегать - "и незаряженное ружье раз в год стреляет" smile

Добавлено через 9 минут и 56 секунд
пример навскидку: поместить в fmOptions указатель на Memo или на ListBox - исключения нет, форма не показана, происходят какие-то действия с "попавшими" объектами - т.е. как минимум происходит нарушения логики программы, как максимум, я уже писал, объекты могут испортиться и программа рухнет.

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)