Ну насчет in detail скучно, а вообще:
1. [критическая ошибка] вызов виртуального метода из конструктора
2. [плохой стиль] вызов виртуального метода из деструктора без обвязки
3. [критическая ошибка] невиртуальный деструктор в классе с явным полиморфным поведением (с учетом п.1 это неважно)
4. [логическая ошибка] объявление виртуальных методов интерфейса с использованием спецификации кода — если это именно интерфейс, то функции нужно было сделать чисто виртуальными
5. [ошибка] выброс исключения в методе, вызываемом в конструкторе без обязки в последнем (с учетом п.1 это неважно)
6. [критическая ошибка] выброс исключения в деструкторе, вызываемом в конструкторе без обязки в последнем
7. [плохой стиль] — выброс исключений неконкретизированного типа (const char*)
8. [плохой стиль] — просто по уродски выглядит — некрасивый код
Здравствуйте, onyXMaster, Вы писали:
XM>Здравствуйте, agrilya, Вы писали:
XM>Ну насчет in detail скучно, а вообще:
<snip>
XM>5. [ошибка] выброс исключения в методе, вызываемом в конструкторе без обязки в последнем (с учетом п.1 это неважно)
А что такое обвязка, и почему плохо из конструктора исключения кидать?
<snip>
Serge.
Hасколько проще была бы жизнь, если бы она была в исходниках.
S>А что такое обвязка, и почему плохо из конструктора исключения кидать?
объект не сконструируется полностью. соответственно не сможет быть удален деструктором. имеем мемори лик.
хорошо про это описано в Scott Meyers. More Effective C++
Здравствуйте, Awaken, Вы писали:
S>>А что такое обвязка, и почему плохо из конструктора исключения кидать?
A>объект не сконструируется полностью.
Ну и чудесно. Не вызовется деструктор для данного обьекта — все предельно справедливо.
A>соответственно не сможет быть удален деструктором.
Вообоще-то деструктор ничего не удаляет... Он обьект уничтожает...
A>имеем мемори лик.
Не имеем. Так как несмотря на то что обьект не создался, память выделенная под него будет освобождена.
A>хорошо про это описано в Scott Meyers. More Effective C++
Вообще-то у Мейерса описан несколько другой случай. И мораль из этого случая несколько другая...
-----------------------
Что же касается flaws — кажется заметил еще один (удивительно как его проглядели остальные )... у AbstractHandle деструктор-то невиртуальный, хотя класс по своим функциям является абстрактным предком...
____________________
God obviously didn't debug, hasn't done any maintenance, and no documentation can be found. Truly amateur work.
Здравствуйте, agrilya, Вы писали:
A>Find as many flows as you can in the following code. Please describe each of them in detail.
[]
Ни одной ошибки в коде нет. Код 100% корректен.
Несколько смущают названия классов и спецификаторы доступа, но мы же не знаем что хотел автор.
Re[4]: How many flows?
От:
Аноним
Дата:
12.06.03 16:49
Оценка:
Здравствуйте, Awaken, Вы писали:
A>объект не сконструируется полностью. соответственно не сможет быть удален деструктором. имеем мемори лик. A>хорошо про это описано в Scott Meyers. More Effective C++
Конструктор не может ничего возвращать вызывающей функции. Исключения — это едиственный и правильный метод сообщить вызывающей функции, что инициализация закончилась неудачно. Никаких мемори ликов в этом случае не будет. Исключение в констркторе -> объект не создан -> память освобождается, деструктор не вызывается потому что нету еще объекта(и уже не будет)
Здравствуйте, agrilya, Вы писали:
A>Find as many flows as you can in the following code. Please describe each of them in detail.
Во-первых, имелось в виду видимо 'flaws', а не 'flows'.
Во-вторых, как уже правильно заметили, без описания замысла автора кода, общих идей дизайна, роли использованных классов и т.п. ни о каких flaws речи быть не может. Без этого можно судить только о том, является ли код well- или ill-formed. Т.е. если код компилируется стандартным компилятором, то никаких flaws в нем нет.
Best regards,
Андрей Тарасевич
Re[2]: How many flows?
От:
Аноним
Дата:
12.06.03 17:35
Оценка:
Здравствуйте, Андрей Тарасевич, Вы писали:
<...>
Я не думаю, что leak при использовании ConcreteHandle — это правильно.
Но, конечно, мы не знаем, что делают функции MyAPIConnect/MyAPIDisconnect — вполне возможно MyAPIConnect печатает "hello word", а MyAPIDisconnect — форматирует C:. Хех.
А>Конструктор не может ничего возвращать вызывающей функции. Исключения — это едиственный и правильный метод сообщить >вызывающей функции, что инициализация закончилась неудачно. Никаких мемори ликов в этом случае не будет. Исключение
я не про данный случай который ничего не делает. представь что в конструкторе создается динамический объект а потом конструктор кидает исключение. этот объект не будет удален деструктором. "откатить" операцию new ты тоже не сможешь
class Unsafe
{
MyString * ss;
public:
Unsafe()
{
ss = new MyString("ccc");
throw 1;
}
~Unsafe()
{
delete ss; // не выполнится никогда
}
};
имхо безопаснее не кидаться исключениями а хранить внутри класса булевый флаг который устанавливается конструктором в true или false при успешной/неуспешной инициализации.
соответственно любой последующий метод этого класса проверяет этот флаг и если false возвращает ошибку.
тут надо по ситуации смотреть , если конструктор не создает объектов которые обязательно требуют уничтожения,
то исключения кидать можно
A>>имеем мемори лик. TMH>Не имеем. Так как несмотря на то что обьект не создался, память выделенная под него будет освобождена.
да нет же. может я неясно выразился. в данном коде используется некая функция connect() и disconnect()
предположим connect открывает некий ресурс ОС (хендл) в предположении что disconnect() его освобождает
connect у нас вызвался, конструктор грохнулся, деструктор вызван не будет и "откатить" вызов connect обратно
мы тоже не можем. вероятно будет утечка ресурсов (не памяти)
Здравствуйте, Вы писали:
> Я не думаю, что leak при использовании ConcreteHandle — это правильно.
А в чем заключается leak?.. Что-то я его в упор не вижу... Этот код вообще безвреден.
ConcreteHandle::connect() и ConcreteHandle::disconnect() при создании/разрушении
объектов типа ConcreteHandle вызваны не будут. Вместо этого будут вызваны
AbstractHandle::connect() и AbstractHandle::disconnect().
Posted via RSDN NNTP Server 1.5 beta
Легче одурачить людей, чем убедить их в том, что они одурачены. — Марк Твен
Re[4]: How many flows?
От:
Аноним
Дата:
12.06.03 18:31
Оценка:
Здравствуйте, Павел Кузнецов, Вы писали:
<...>
Оопс, лажа с моей стороны.
Пойду, сделаю с собой что-нибудь, хех.
Здравствуйте, Awaken, Вы писали:
А>>Конструктор не может ничего возвращать вызывающей функции. Исключения — это едиственный и правильный метод сообщить >вызывающей функции, что инициализация закончилась неудачно. Никаких мемори ликов в этом случае не будет. Исключение
A>я не про данный случай который ничего не делает. представь что в конструкторе создается динамический объект а потом конструктор кидает исключение. этот объект не будет удален деструктором. "откатить" операцию new ты тоже не сможешь
A>
A>class Unsafe
A>{
A> MyString * ss;
A>public:
A> Unsafe()
A> {
A> ss = new MyString("ccc");
A> throw 1;
A> }
A> ~Unsafe()
A> {
A> delete ss; // не выполнится никогда
A> }
A>};
A>
A>имхо безопаснее не кидаться исключениями а хранить внутри класса булевый флаг который устанавливается конструктором в true или false при успешной/неуспешной инициализации.
Ну так а при чем здесь именно конструктор? Такое может произойти в любой функции: создается динамический объект, потом кидается исключение и ага... Так что из этого следует, что если в некоторой функции создаются динамические объекты, то эта функция не может кидать исключения? Это полная ерунда. Код, создающий динамические объекты, должен быть написан так, чтобы он был безопасным с точки зрения исключений.
В данном случае твой код не удовлетворяет этому требованию из-за того, что ты небезопасным образом создаешь динамический объект. Это твоя ошибка. Ни исключения, ни динамические объекты тут ни в чем не виноваты. Создавай объект безопасным образом — и никаких проблем с исключениями не будет. Это можно сделать разными способами. Можно так:
Здравствуйте, Awaken, Вы писали:
A>я не про данный случай который ничего не делает. представь что в конструкторе создается динамический объект а потом конструктор кидает исключение. этот объект не будет удален деструктором. "откатить" операцию new ты тоже не сможешь
A>
A>class Unsafe
A>{
A> MyString * ss;
A>public:
A> Unsafe()
A> {
A> ss = new MyString("ccc");
A> throw 1;
A> }
A> ~Unsafe()
A> {
A> delete ss; // не выполнится никогда
A> }
A>};
A>
A>имхо безопаснее не кидаться исключениями а хранить внутри класса булевый флаг который устанавливается конструктором в true или false при успешной/неуспешной инициализации. A>соответственно любой последующий метод этого класса проверяет этот флаг и если false возвращает ошибку. A>тут надо по ситуации смотреть , если конструктор не создает объектов которые обязательно требуют уничтожения, A>то исключения кидать можно
Да, в приведенном коде delelte ss не выполниться никогда. Но это просто пример небезопастного к исключениям кода. Так делать не надо. Если конструкотор помимо захвата каких либо ресурсов делает еще что-то что может кинуться исключением, то захват и освобождение ресурсов надо выделять в отдельный класс и инициализировать его до момента возможного возбуждения исключения. В приведенном тобой случае изобретать велосипед не надо — ss должен быть не MyString* , а std::auto_ptr<MyString>.
Safe() : ss(new MyString("ccc"))
{
throw 1;
}
После throw 1 деструктор ss удалит все что надо удалить.
A>>>имеем мемори лик. TMH>>Не имеем. Так как несмотря на то что обьект не создался, память выделенная под него будет освобождена.
A>да нет же. может я неясно выразился. в данном коде используется некая функция connect() и disconnect() A>предположим connect открывает некий ресурс ОС (хендл) в предположении что disconnect() его освобождает A>connect у нас вызвался, конструктор грохнулся, деструктор вызван не будет и "откатить" вызов connect обратно A>мы тоже не можем. вероятно будет утечка ресурсов (не памяти)
Один момент. connect() вызывается из конструктора базового класса. Поэтому, хотя эта функция и виртуальная, компилятор сгенирирует статические вызов. Т.е. позовется AbstractHandle::connect(), а она пустая! Никакой утечки нет.