Исключения(exception) и вызов деструкторов
От: Аноним  
Дата: 01.08.02 12:46
Оценка:
В этом варианте при возникновение исключения вызывается деструктор статического класса, но если я убираю строку "cout <<"XZ\n"<<endl;" (в ф-ии f1() ), то вызова этого деструктора не вижу.
#include "stdafx.h"
#include <iostream.h>

void f1();
class Ctest
{
    
    public:
        int iType; // 1- heap ; 2- stack
        Ctest(int _iType): iType(_iType) { cout << "test "<<iType<< "\n"<<endl; }
        ~Ctest() { cout <<"~test "<<iType<< "\n"<<endl;    }

};

int main(int argc, char* argv[])
{

    try 
    //__try 
    {    
        printf("start __try\n");
        f1(); // - âíåé áóäåò èñêëþ÷åíèå
        printf("end __try\n");
    } 
    catch(...)
    //__except (EXCEPTION_EXECUTE_HANDLER)
    { 
        printf("__except\n");
    } 

    printf("end example\n");
    return 0;
}

void f1()
{
    Ctest Ct2(2);// 2- stack
    
    //cout <<"XZ\n"<<endl;    

    DWORD dw=0;
    dw = 5/dw;
    DWORD *pdw=0; *pdw=1;

    printf("end f1\n");
}
Re: Исключения(exception) и вызов деструкторов
От: DarkGray Россия http://blog.metatech.ru/post/ogni-razrabotki.aspx
Дата: 01.08.02 13:04
Оценка: 8 (2)
Здравствуйте Аноним, Вы писали:

А>В этом варианте при возникновение исключения вызывается деструктор статического класса, но если я убираю строку "cout <<"XZ\n"<<endl;" (в ф-ии f1() ), то вызова этого деструктора не вижу.


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

Когда ты добавляешь вызов cout << "XZ", то компилятор видит, что в данном блоке может возникнуть C++-исключение, поэтому надо сгенерировать код "размотки".

P.S. Деление на ноль — это не C++-исключение, это "машинное" исключение, которое для программы и компилятора является полной неожиданностью в run-time, а на этапе компиляции его не видно.
Re: Исключения(exception) и вызов деструкторов
От: santucco  
Дата: 01.08.02 13:08
Оценка:
Здравствуйте Аноним, Вы писали:

А>В этом варианте при возникновение исключения вызывается деструктор статического класса, но если я убираю строку "cout <<"XZ\n"<<endl;" (в ф-ии f1() ), то вызова этого деструктора не вижу.

А>
А>#include "stdafx.h"
А>#include <iostream.h>

А>void f1();
А>class Ctest
А>{
А>    
А>    public:
А>        int iType; // 1- heap ; 2- stack
А>        Ctest(int _iType): iType(_iType) { cout << "test "<<iType<< "\n"<<endl; }
А>        ~Ctest() { cout <<"~test "<<iType<< "\n"<<endl;    }

А>};

А>int main(int argc, char* argv[])
А>{

А>    try 
А>    //__try 
А>    {    
А>        printf("start __try\n");
А>        f1(); // - âíåé áóäåò èñêëþ÷åíèå
А>        printf("end __try\n");
А>    } 
А>    catch(...)
А>    //__except (EXCEPTION_EXECUTE_HANDLER)
А>    { 
А>        printf("__except\n");
А>    } 

А>    printf("end example\n");
А>    return 0;
А>}

А>void f1()
А>{
А>    Ctest Ct2(2);// 2- stack
А>    
А>    //cout <<"XZ\n"<<endl;    

А>    DWORD dw=0;
А>    dw = 5/dw;
А>    DWORD *pdw=0; *pdw=1;

А>    printf("end f1\n");
А>}
А>

Насколько я понимаю, деление на ноль вызывает исключение, обработка которого ложится на плечи операционой системы и не имеет к исключениям С++ никакого отношения. Под FreeBSD данный пример приводит к тому, система шлет сигнал SIGFPE (Floating point exception) и валит прогу в core.
Не стреляйте в пианиста, он играет как умеет...
Re[2]: Исключения(exception) и вызов деструкторов
От: DarkGray Россия http://blog.metatech.ru/post/ogni-razrabotki.aspx
Дата: 01.08.02 13:12
Оценка:
Здравствуйте santucco, Вы писали:

S>Насколько я понимаю, деление на ноль вызывает исключение, обработка которого ложится на плечи операционой системы и не имеет к исключениям С++ никакого отношения. Под FreeBSD данный пример приводит к тому, система шлет сигнал SIGFPE (Floating point exception) и валит прогу в core.


Под VC try/catch имеет возможность поймать системное исключение.
В данном случае вся проблема в том, что из-за "оптимизации" VC не генерируется код размотки стека, если не видит выброса C++-исключений
Re[3]: Исключения(exception) и вызов деструкторов
От: santucco  
Дата: 01.08.02 13:15
Оценка:
Здравствуйте DarkGray, Вы писали:

DG>Здравствуйте santucco, Вы писали:


S>>Насколько я понимаю, деление на ноль вызывает исключение, обработка которого ложится на плечи операционой системы и не имеет к исключениям С++ никакого отношения. Под FreeBSD данный пример приводит к тому, система шлет сигнал SIGFPE (Floating point exception) и валит прогу в core.


DG>Под VC try/catch имеет возможность поймать системное исключение.

DG>В данном случае вся проблема в том, что из-за "оптимизации" VC не генерируется код размотки стека, если не видит выброса C++-исключений
"Мы в Microsoft считаем, что стандарт всегда можно улучшить" (Дейл Роджерсон, если не ошибаюсь)
Не стреляйте в пианиста, он играет как умеет...
Re[4]: Исключения(exception) и вызов деструкторов
От: DarkGray Россия http://blog.metatech.ru/post/ogni-razrabotki.aspx
Дата: 01.08.02 13:19
Оценка:
Здравствуйте santucco, Вы писали:

S>>>Насколько я понимаю, деление на ноль вызывает исключение, обработка которого ложится на плечи операционой системы и не имеет к исключениям С++ никакого отношения. Под FreeBSD данный пример приводит к тому, система шлет сигнал SIGFPE (Floating point exception) и валит прогу в core.


DG>>Под VC try/catch имеет возможность поймать системное исключение.

DG>>В данном случае вся проблема в том, что из-за "оптимизации" VC не генерируется код размотки стека, если не видит выброса C++-исключений
S>"Мы в Microsoft считаем, что стандарт всегда можно улучшить" (Дейл Роджерсон, если не ошибаюсь)

Все-таки это лучше, чем core dumped из-за простого деления на ноль
Re[5]: Исключения(exception) и вызов деструкторов
От: Аноним  
Дата: 01.08.02 13:37
Оценка:
Здравствуйте DarkGray,
>Насколько я понимаю работу исключений в VC6, это связано с тем, что если компилятор не видит >генерации C++-исключений, то он и не создает код, который отвечает за размотку стека при исключениях.

Пожалуй в этом что-то есть.
Когда я между
Ctest Ct2(2); и делением на 0х0 вставляю вызов f2() описанной: void f2(){}
Вызов деструктора появляется
Re[5]: Исключения(exception) и вызов деструкторов
От: santucco  
Дата: 01.08.02 13:42
Оценка:
Здравствуйте DarkGray, Вы писали:

DG>Здравствуйте santucco, Вы писали:


S>>>>Насколько я понимаю, деление на ноль вызывает исключение, обработка которого ложится на плечи операционой системы и не имеет к исключениям С++ никакого отношения. Под FreeBSD данный пример приводит к тому, система шлет сигнал SIGFPE (Floating point exception) и валит прогу в core.


DG>>>Под VC try/catch имеет возможность поймать системное исключение.

DG>>>В данном случае вся проблема в том, что из-за "оптимизации" VC не генерируется код размотки стека, если не видит выброса C++-исключений
S>>"Мы в Microsoft считаем, что стандарт всегда можно улучшить" (Дейл Роджерсон, если не ошибаюсь)

DG>Все-таки это лучше, чем core dumped из-за простого деления на ноль

Ну если серьезно, то я бы не сказал что лучше, потому что "простое деление на ноль" на самом деле довольно серьезная ошибка программиста.
Впрочем, мне не хотелось бы затевать новый "религиозный" флейм.
И если народ привык полагаться на компилятор в подобных случаях — то регистр флагов ему в руки
Не стреляйте в пианиста, он играет как умеет...
Re[6]: Исключения(exception) и вызов деструкторов
От: DarkGray Россия http://blog.metatech.ru/post/ogni-razrabotki.aspx
Дата: 01.08.02 14:00
Оценка:
Здравствуйте santucco, Вы писали:

DG>>Все-таки это лучше, чем core dumped из-за простого деления на ноль

S>Ну если серьезно, то я бы не сказал что лучше, потому что "простое деление на ноль" на самом деле довольно серьезная ошибка программиста.

Вот только пользователи это слышать нихотят, а начинают при очередном падении топать ногами и вспоминать Билл Гейтса.

S>И если народ привык полагаться на компилятор в подобных случаях — то регистр флагов ему в руки


Дык, все ошибки не исправишь, а так хоть все остальное будет работать.
Re: Исключения(exception) и вызов деструкторов
От: dupamid Россия  
Дата: 02.08.02 06:17
Оценка:
Здравствуйте Аноним, Вы писали:

А>В этом варианте при возникновение исключения вызывается деструктор статического класса, но если я убираю строку "cout <<"XZ\n"<<endl;" (в ф-ии f1() ), то вызова этого деструктора не вижу.

А>
А>#include "stdafx.h"
А>#include <iostream.h>

А>void f1();
А>class Ctest
А>{
А>    
А>    public:
А>        int iType; // 1- heap ; 2- stack
А>        Ctest(int _iType): iType(_iType) { cout << "test "<<iType<< "\n"<<endl; }
А>        ~Ctest() { cout <<"~test "<<iType<< "\n"<<endl;    }

А>};

А>int main(int argc, char* argv[])
А>{

А>    try 
А>    //__try 
А>    {    
А>        printf("start __try\n");
А>        f1(); // - âíåé áóäåò èñêëþ÷åíèå
А>        printf("end __try\n");
А>    } 
А>    catch(...)
А>    //__except (EXCEPTION_EXECUTE_HANDLER)
А>    { 
А>        printf("__except\n");
А>    } 

А>    printf("end example\n");
А>    return 0;
А>}

А>void f1()
А>{
А>    Ctest Ct2(2);// 2- stack
А>    
А>    //cout <<"XZ\n"<<endl;    

А>    DWORD dw=0;
А>    dw = 5/dw;
А>    DWORD *pdw=0; *pdw=1;

А>    printf("end f1\n");
А>}
А>


Если есть желание чтобы компилятор правильно ловил такие исключения как деление на ноль в С++ try/catch блоках, то для MS Visual C++ нужно включить поддержку для асинхронных исключений, при этом код заметно распухнет и будет медленнее, но будет все правильно ловить и вызывать деструкторы, по умолчанию она выключена. По Стандарту все исключения синхронные, так что поддержка асинхронных исключений это расширение Стандарт MS'ом.
Re[2]: Исключения(exception) и вызов деструкторов
От: Павел Кузнецов  
Дата: 02.08.02 07:19
Оценка:
Здравствуйте dupamid, Вы писали:

D>По Стандарту все исключения синхронные, так что поддержка асинхронных исключений это расширение Стандарт MS'ом.


Маленькое буквоедство: стандарт не различает синхронные и асинхронные исключения, просто говорит, что деление на ноль, в частности, вызывает неопределенное поведение. Что делать в ответ на неопределенное поведение — дело разработчиков компилятора.
Легче одурачить людей, чем убедить их в том, что они одурачены. — Марк Твен
Re[3]: Исключения(exception) и вызов деструкторов
От: dupamid Россия  
Дата: 02.08.02 07:37
Оценка:
Здравствуйте Павел Кузнецов, Вы писали:

ПК>Маленькое буквоедство: стандарт не различает синхронные и асинхронные исключения, просто говорит, что деление на ноль, в частности, вызывает неопределенное поведение. Что делать в ответ на неопределенное поведение — дело разработчиков компилятора.


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

Кстати, правильная работа приводимого примера обеспечивается как раз из-за вызова функции вывода в поток, так как компилятор не знает, выбрасывает ли она исключения, он считает, что она их выбрасывает и генерирует соответствующий код для их поимки.
Re[4]: Исключения(exception) и вызов деструкторов
От: BK  
Дата: 02.08.02 08:17
Оценка:
Здравствуйте dupamid, Вы правы:
Ответ оказался прост. Нашел у Джон Роббинс "Отладка приложений в Windows"
В VC++ у компилятора есть два ключа: /EHa (/EHac) и /EHs (/EHsc , /GX)
В VC++ 5.0 поумолчанию — /EHa — как все и считали
В VC++ 6.0 поумолчанию (см. /GX) — /EHs — обработка исключений/раскрутка стека создается только если:
время жизни локального обьекта Ctest Ct2(2); пересекается с
а)вызовом ф-ии
б)throw

поэтому
f1(){
int *pi=new int;//-бесполезно, не пересекается со временем жизни Ct2 (деструктора не будет)
Ctest Ct2(2);
//exception
int *pi=new int;}//-будет деструктор
}

Но вот вопрос, а почему
cout <<"XZ\n"<<endl; — вызов ф-ии
printf("end f1\n"); — а это с точки зрения компилятора уже не вызов ф-ии ????
Re[5]: Исключения(exception) и вызов деструкторов
От: dupamid Россия  
Дата: 02.08.02 08:23
Оценка:
Здравствуйте BK, Вы писали:

BK>Но вот вопрос, а почему

BK>cout <<"XZ\n"<<endl; — вызов ф-ии
BK>printf("end f1\n"); — а это с точки зрения компилятора уже не вызов ф-ии ????

Вызов, но функции extern "C", которые не должны выбрасывать исключения, хотя на самом деле могут и от этого может быть множестов проблем.
Re[2]: Исключения(exception) и вызов деструкторов
От: Алекс Россия http://wise-orm.com
Дата: 02.08.02 08:50
Оценка:
Здравствуйте DarkGray, Вы писали:

DG>Здравствуйте Аноним, Вы писали:


А>>В этом варианте при возникновение исключения вызывается деструктор статического класса, но если я убираю строку "cout <<"XZ\n"<<endl;" (в ф-ии f1() ), то вызова этого деструктора не вижу.


DG>Насколько я понимаю работу исключений в VC6, это связано с тем, что если компилятор не видит генерации C++-исключений, то он и не создает код, который отвечает за размотку стека при исключениях.


DG>Когда ты добавляешь вызов cout << "XZ", то компилятор видит, что в данном блоке может возникнуть C++-исключение, поэтому надо сгенерировать код "размотки".


DG>P.S. Деление на ноль — это не C++-исключение, это "машинное" исключение, которое для программы и компилятора является полной неожиданностью в run-time, а на этапе компиляции его не видно.


на сколько я помню это называется синхронной обработкой исключений при асинхронной все иначе.
регулируется это дело опциями /Eh
Re[4]: Исключения(exception) и вызов деструкторов
От: Павел Кузнецов  
Дата: 02.08.02 08:59
Оценка:
Здравствуйте dupamid, Вы писали:

ПК>>Маленькое буквоедство: стандарт не различает синхронные и асинхронные исключения, просто говорит, что деление на ноль, в частности, вызывает неопределенное поведение. Что делать в ответ на неопределенное поведение — дело разработчиков компилятора.


D>По Стандарту исключения синхронные — в том смысле, что они происходят по запросу из программы в явном виде посредством throw и никак иначе,


Не обязательно. В случае undefined behavior разработчики компилятора имеют право определить поведение программы, как им заблагорассудится, в т.ч. и бросить исключение. Это я к тому, что возбуждение исключения в случае деления на ноль расширением не является, а является одним из вариантов неопределенного поведения.

D>Понятия синхронных и асинхронных исключений, с которыми я оперировал, взяты не из Стандарта, а из описания MS, но они достаточно наглядны и позволяют разобраться, в чем здесь дело и как с этим бороться (...)


Дык, по существу-то я ничего и не возражал. Просто, сканируя этот тред на случай, что кто-то правильный ответ уже дал, нашел твой, с которым согласен, за исключением формулировки, касающейся расширения :-)
Легче одурачить людей, чем убедить их в том, что они одурачены. — Марк Твен
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.