Существует ли способ узнать текущее исключение?
От: valker  
Дата: 02.04.10 12:06
Оценка:
Здравствуйте!

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

Заранее спасибо за ответы.
Re: Существует ли способ узнать текущее исключение?
От: Alexander G Украина  
Дата: 02.04.10 12:13
Оценка: +1
Здравствуйте, valker, Вы писали:

V>Собственно, существует ли способ узнать текущее исключение находясь в деструкторе?



if (!std::uncaught_exception())
{
  нет_никакого_текущего_исключения();
}
else
{
  try
  {
    throw; 
  }
  catch(std::exception& ex)
  {
    так_вот_же_оно(ex);
  }
  catch(...)
  {
    неизвестное_науке_исключение();
  }
}




Ну и разумеется, наличие текущего исключение не означает, что данный деструктор был вызван в процессе раскрутки, и что новое исключение из него приведёт к аварийному заваршению.
Русский военный корабль идёт ко дну!
Re[2]: Существует ли способ узнать текущее исключение?
От: valker  
Дата: 02.04.10 12:21
Оценка:
Здравствуйте, Alexander G, Вы писали:

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


V>>Собственно, существует ли способ узнать текущее исключение находясь в деструкторе?


AG>Ну и разумеется, наличие текущего исключение не означает, что данный деструктор был вызван в процессе раскрутки, и что новое исключение из него приведёт к аварийному заваршению.


Спасибо.
Следует ли понимать последнюю фразу так что если в деструкторе обнаружено текущее исключение — это может означать:
1. вызов деструктора раскрутчиком стека
2. вызов деструктора внутри какого-либо блока catch или функций, которые вызываются из этого блока.
???
Re[3]: Существует ли способ узнать текущее исключение?
От: Alexander G Украина  
Дата: 02.04.10 12:41
Оценка:
Извините, кажется я не прав, код мой не рабоает.
Русский военный корабль идёт ко дну!
Re: Существует ли способ узнать текущее исключение?
От: saf_e  
Дата: 02.04.10 14:17
Оценка:
Здравствуйте, valker, Вы писали:

V>Здравствуйте!


V>Собственно, существует ли способ узнать текущее исключение находясь в деструкторе?

V>Нестандартные расширения отдельных компиляторов в этой связи тоже интересуют.

V>Заранее спасибо за ответы.


Не буду утверждать на 100%, ибо не уверен. Но на 99% -- нет.

Причины -- для деструктора все равно в каком контексте он выполняется. Можно рискнуть залезть в "стаб" обработчика SEH, и посмотреть что можно узнать. Но вы получите результат для данной конкретной версии, данного конкретного компилятора, хотя может коллеги меня и поправят.

Можете копнуть сюда:

_tiddata *p_data = _getptd();

Там есть поле

void * _curexception; /* current exception */

Но в моем случае это не сработало, и во время деструкции при эксепшене, и при разрушении ч-з delete, содержимое структуры идентично

И опять таки она недокументированна, и никто не гарантирует, что разрабы компилятора что-то не поменяют в ней самой, или в том как ее используют или вообще уберут
Re: Существует ли способ узнать текущее исключение?
От: saf_e  
Дата: 02.04.10 14:35
Оценка:
Здравствуйте, valker, Вы писали:

V>Здравствуйте!


V>Собственно, существует ли способ узнать текущее исключение находясь в деструкторе?

V>Нестандартные расширения отдельных компиляторов в этой связи тоже интересуют.

V>Заранее спасибо за ответы.


Вот, неплохая статья:
http://www.codeproject.com/KB/cpp/exceptionhandler.aspx
Re: Существует ли способ узнать текущее исключение?
От: Шахтер Интернет  
Дата: 02.04.10 16:21
Оценка:
Здравствуйте, valker, Вы писали:

V>Здравствуйте!


V>Собственно, существует ли способ узнать текущее исключение находясь в деструкторе?

V>Нестандартные расширения отдельных компиляторов в этой связи тоже интересуют.

Какое из? Их может быть несколько. В данной постановке вопрос не имеет смысла.

V>Заранее спасибо за ответы.
В XXI век с CCore.
Копай Нео, копай -- летать научишься. © Matrix. Парадоксы
Re: Существует ли способ узнать текущее исключение?
От: zaufi Земля  
Дата: 02.04.10 22:17
Оценка:
Здравствуйте, valker, Вы писали:

V>Здравствуйте!


V>Собственно, существует ли способ узнать текущее исключение находясь в деструкторе?

V>Нестандартные расширения отдельных компиляторов в этой связи тоже интересуют.

ну раз так... у гцц есть возможность получить указатель на std::type_info текущего исключения функцией __cxa_current_exception_type

V>Заранее спасибо за ответы.
Re[2]: Существует ли способ узнать текущее исключение?
От: valker  
Дата: 03.04.10 05:55
Оценка:
Здравствуйте, zaufi, Вы писали:

Z>ну раз так... у гцц есть возможность получить указатель на std::type_info текущего исключения функцией __cxa_current_exception_type


Интересная вещь! Спасибо! Но только там тип-инфо... а мне бы сам объект исключения...
Re: Существует ли способ узнать текущее исключение?
От: gear nuke  
Дата: 05.04.10 09:53
Оценка: 4 (1)
Здравствуйте, valker, Вы писали:

V>Собственно, существует ли способ узнать текущее исключение находясь в деструкторе?


C++0x
std::exception_ptr std::current_exception();
People who are more than casually interested in computers should have at least some idea of what the underlying hardware is like. Otherwise the programs they write will be pretty weird (c) D.Knuth
Re[2]: Существует ли способ узнать текущее исключение?
От: gear nuke  
Дата: 05.04.10 10:02
Оценка:
Здравствуйте, saf_e, Вы писали:

_> Можете копнуть сюда:


_> _tiddata *p_data = _getptd();


_> Там есть поле


_> void * _curexception; /* current exception */


_> Но в моем случае это не сработало, и во время деструкции при эксепшене, и при разрушении ч-з delete, содержимое структуры идентично


Структура должна иметь тип EXCEPTION_POINTERS, может быть следовало смотреть дальше. В любом случае, это именно оно.

Чтобы проще копать, можно подсмотреть current_exception(), но там tiddata не совместима с MSVC.

_> И опять таки она недокументированна, и никто не гарантирует, что разрабы компилятора что-то не поменяют в ней самой, или в том как ее используют или вообще уберут


Явно конечно никто не гарантирует, но в коде диспетчера исключений заложена совместимость как обратная, так и вперед. См в частности ThrowInfo::pForwardCompat здесь
People who are more than casually interested in computers should have at least some idea of what the underlying hardware is like. Otherwise the programs they write will be pretty weird (c) D.Knuth
Re[3]: Существует ли способ узнать текущее исключение?
От: saf_e  
Дата: 06.04.10 08:47
Оценка:
Здравствуйте, gear nuke, Вы писали:

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


_>> Можете копнуть сюда:


_>> _tiddata *p_data = _getptd();


_>> Там есть поле


_>> void * _curexception; /* current exception */


_>> Но в моем случае это не сработало, и во время деструкции при эксепшене, и при разрушении ч-з delete, содержимое структуры идентично


GN>Структура должна иметь тип EXCEPTION_POINTERS, может быть следовало смотреть дальше. В любом случае, это именно оно.


У меня этот указатель (и все соседние смотрели на NULL) так что...

GN>Чтобы проще копать, можно подсмотреть current_exception(), но там tiddata не совместима с MSVC.


Как в 2005 студии раскрутка происходит я увидел вроде нигде указатель/инфа не запоминались, но зуб давать не буду

_>> И опять таки она недокументированна, и никто не гарантирует, что разрабы компилятора что-то не поменяют в ней самой, или в том как ее используют или вообще уберут


GN>Явно конечно никто не гарантирует, но в коде диспетчера исключений заложена совместимость как обратная, так и вперед. См в частности ThrowInfo::pForwardCompat здесь


Оно конечно хорошо, но никто не гарантирует, что код диспетчера не перепишут чуть больше чем полностью (потому что, механизм перестанет устраивать, например). В любом случае, если что-то не задокументировано стандартом, а вы на это заложились, то пенять потом не на кого
Re[4]: Существует ли способ узнать текущее исключение?
От: gear nuke  
Дата: 06.04.10 12:12
Оценка:
Здравствуйте, saf_e, Вы писали:

_>У меня этот указатель (и все соседние смотрели на NULL) так что...


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

Фрагмент CRT котрый идёт с cl.exe 13.10
.text:000006E4 void * __cdecl CallCatchBlock(struct EHExceptionRecord * thrownException, struct EHRegistrationNode *, struct _CONTEXT *, struct _s_FuncInfo const *, void *, int, unsigned long) proc near
.text:000006E4                                         ; CODE XREF: CatchIt(EHExceptionRecord *,EHRegistrationNode *,_CONTEXT *,void *,_s_FuncInfo const *,_s_HandlerType const *,_s_CatchableType const *,_s_TryBlockMapEntry const *,int,EHRegistrationNode *,uchar)+54p
.text:000006E4

.text:000006E4
.text:000006E4                 push    40h ; '@'
.text:000006E6                 push    offset $T22843
.text:000006EB                 call    __SEH_prolog
.text:000006F0                 mov     ebx, ecx
.text:000006F2                 mov     edi, [ebp+arg_4]
.text:000006F5                 mov     esi, [ebp+thrownException]
.text:000006F8                 mov     [ebp+var_20], ebx
.text:000006FB                 and     [ebp+var_48], 0
.text:000006FF                 mov     eax, [edi-4]
.text:00000702                 mov     [ebp+var_38], eax
.text:00000705                 push    dword ptr [esi+18h] ; void *
.text:00000708                 lea     eax, [ebp+var_50]
.text:0000070B                 push    eax             ; struct FrameInfo *
.text:0000070C                 call    _CreateFrameInfo(FrameInfo *,void *)
.text:00000711                 pop     ecx
.text:00000712                 pop     ecx
.text:00000713                 mov     [ebp+var_3C], eax
.text:00000716                 call    __getptd
.text:0000071B                 mov     eax, [eax+78h]
.text:0000071E                 mov     [ebp+var_40], eax
.text:00000721                 call    __getptd
.text:00000726                 mov     eax, [eax+7Ch]
.text:00000729                 mov     [ebp+var_44], eax
.text:0000072C                 call    __getptd
.text:00000731                 mov     [eax+78h], esi    ; вот сохранение
.text:00000734                 call    __getptd
.text:00000739                 mov     ecx, [ebp+context]
.text:0000073C                 mov     [eax+7Ch], ecx


_>Как в 2005 студии раскрутка происходит я увидел


Каким образом? Студийный отладчик в диспетчер исключений не должен заходить.

_>Оно конечно хорошо, но никто не гарантирует, что код диспетчера не перепишут чуть больше чем полностью (потому что, механизм перестанет устраивать, например).


Несомненно, всегда можно найти 100500 причин ничего не далеть Есть задача и её нужно решать. Не пойму, откуда могут возникнуть проблемы? Берётся конкретная версия Студии и разбирается, проблемы возможны при переходе на слудеющую версию с другим определением tiddata, но не обязательно же не неё переходить
People who are more than casually interested in computers should have at least some idea of what the underlying hardware is like. Otherwise the programs they write will be pretty weird (c) D.Knuth
Re[5]: Существует ли способ узнать текущее исключение?
От: saf_e  
Дата: 06.04.10 13:29
Оценка:
Здравствуйте, gear nuke, Вы писали:

GN>Это очередное подтверждение моего мнения о том, что динамический анализ (то есть в отладчике) может не дать полной картины, в отличие от статического (в дизассемблере)


Не совсем понятно, тогда какой от этого толк, если на момент исполнения инфа недоступна?

GN>Каким образом? Студийный отладчик в диспетчер исключений не должен заходить.


Его можно вежливо попросить

_>>Оно конечно хорошо, но никто не гарантирует, что код диспетчера не перепишут чуть больше чем полностью (потому что, механизм перестанет устраивать, например).


GN>Несомненно, всегда можно найти 100500 причин ничего не далеть Есть задача и её нужно решать. Не пойму, откуда могут возникнуть проблемы? Берётся конкретная версия Студии и разбирается, проблемы возможны при переходе на слудеющую версию с другим определением tiddata, но не обязательно же не неё переходить


Когда через н-цать лет после этого все-таки придется перейти на другой компилятор, тот кто будет долго ловить трудноуловимый баг связанны с вашим хаком расскажет о вас много всего интересного
Re[6]: Существует ли способ узнать текущее исключение?
От: gear nuke  
Дата: 06.04.10 13:47
Оценка:
Здравствуйте, saf_e, Вы писали:

_>Не совсем понятно, тогда какой от этого толк, если на момент исполнения инфа недоступна?


В какой именно момент недоступна? На момент выполнения catch clause — доступна, см. исходник.

GN>>Каким образом? Студийный отладчик в диспетчер исключений не должен заходить.


_>Его можно вежливо попросить


Это где-то в настройках делается, или как? Я больше пользуюсь WinDbg.

_>Когда через н-цать лет после этого все-таки придется перейти на другой компилятор, тот кто будет долго ловить трудноуловимый баг связанны с вашим хаком расскажет о вас много всего интересного


Ему сначала придётся суметь собрать проект.
static_assert(_MSC_VER == ..., "make sure C++ runtime is supported");
People who are more than casually interested in computers should have at least some idea of what the underlying hardware is like. Otherwise the programs they write will be pretty weird (c) D.Knuth
Re[7]: Существует ли способ узнать текущее исключение?
От: saf_e  
Дата: 06.04.10 13:52
Оценка:
Здравствуйте, gear nuke, Вы писали:

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


_>>Не совсем понятно, тогда какой от этого толк, если на момент исполнения инфа недоступна?


GN>В какой именно момент недоступна? На момент выполнения catch clause — доступна, см. исходник.


Когда происходил вызов деструктора моего объекта в результате раскрутки стека -- из информации о потоке я не смог ничего вытянуть. (MSVC 2005)

GN>>>Каким образом? Студийный отладчик в диспетчер исключений не должен заходить.


_>>Его можно вежливо попросить


GN>Это где-то в настройках делается, или как? Я больше пользуюсь WinDbg.


Заходим в дизассемблер по RMC и видим что находится вокруг -- дальше ставим бряки в нужные места.
Можно еще включить во вкладке "Debugger" ловить все/нужные исключения.

_>>Когда через н-цать лет после этого все-таки придется перейти на другой компилятор, тот кто будет долго ловить трудноуловимый баг связанны с вашим хаком расскажет о вас много всего интересного


GN>Ему сначала придётся суметь собрать проект.

GN>
static_assert(_MSC_VER == ..., "make sure C++ runtime is supported");


Прошу прощения пропустил, это уже лучше, что впрочем, лишь избавит от ловли бага, но не поможет лечению
Re[8]: Существует ли способ узнать текущее исключение?
От: gear nuke  
Дата: 06.04.10 14:26
Оценка:
Здравствуйте, saf_e, Вы писали:

_>Когда происходил вызов деструктора моего объекта в результате раскрутки стека -- из информации о потоке я не смог ничего вытянуть. (MSVC 2005)


Ок, сейчас угадаю в чём проблема.

Вот определение текущего исключения:

The exception with the most recently activated handler that is still active is called the currently handled exception.

То есть оно существует только в рамках активного обработчика, и есть один нюанс:

A handler is considered active when initialization is complete for the formal parameter (if any) of the catch clause. [ Note: the stack will have been unwound at that point. —end note ]

перед вызовом обработчика объекты уже разрушены

Поэтому вот в таком случае в дуструкторе obj информации об исключении нет:
try
{
  Foo obj;
  throw 0;
}
catch(...)
{

}

И случай с nullptr описан в драфте

18.8.5 Exception Propagation

exception_ptr current_exception();

7 Returns: An exception_ptr object that refers to the currently handled exception (15.3) or a copy of the currently handled exception, or a null exception_ptr object if no exception is being handled.


Моя ошибка была в том, что я не различаю понятия "текущее исключение" и "currently handled exception" (поскольку с точки зрения Стандарта это одно и тоже) и под деструктором понимаю общий случай, а не частный, как выше.

_>Прошу прощения пропустил, это уже лучше, что впрочем, лишь избавит от ловли бага, но не поможет лечению


Ну вообюще-то не я начал предлагать ковырять рантайм
People who are more than casually interested in computers should have at least some idea of what the underlying hardware is like. Otherwise the programs they write will be pretty weird (c) D.Knuth
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.