информационная безопасность
без паники и всерьез
 подробно о проектеRambler's Top100
Атака на InternetВсе любят мед
BugTraq.Ru
Русский BugTraq
 Анализ криптографических сетевых... 
 Модель надежности двухузлового... 
 Специальные марковские модели надежности... 
 Бэкдор в xz/liblzma, предназначенный... 
 Три миллиона электронных замков... 
 Doom на газонокосилках 
главная обзор RSN блог библиотека закон бред форум dnet о проекте
bugtraq.ru / форум / programming
Имя Пароль
ФОРУМ
если вы видите этот текст, отключите в настройках форума использование JavaScript
регистрация





Легенда:
  новое сообщение
  закрытая нитка
  новое сообщение
  в закрытой нитке
  старое сообщение
  • Напоминаю, что масса вопросов по функционированию форума снимается после прочтения его описания.
  • Новичкам также крайне полезно ознакомиться с данным документом.
Согласен. Такая формулировка будет более выдержанной и... 16.08.04 01:04  Число просмотров: 1651
Автор: void <Grebnev Valery> Статус: Elderman
<"чистая" ссылка>
>Теоретически преград к реализации передачи
> исключений между исполняемыми модулями в общем-то нет,
> вопрос в корректной реализации раскрутки стека.

Согласен. Такая формулировка будет более выдержанной и толковой, чем моя.

> Надеяться на обработку флага ошибки вместо исключения -
> плохая практика

Но, если есть вылезанная функция ДЛЛ, что возвращает HRESULT-код, то почему не ограничиться только анализом этого в вызывающем коде?
Мы ж не анализируем в ТРАЙ/КЭТЧ блоке результаты методов КОМ. Почти всегда идет анализ ! FAILED( rc ), или S_OK.
<programming>
[C++] Рассудите, плз. про экзепшн в ДЛЛ 15.08.04 02:43   [Den]
Автор: void <Grebnev Valery> Статус: Elderman
<"чистая" ссылка>
Вышел спор. Пока без крови ;))
Суть такова. Есть ДЛЛ, где криво написана одна из функций. Известно, что экзепшн внутри самой функции ДЛЛ не обрабатывается. Сорца той ДЛЛ нет, чтобы подправить.

Товарищь утверждает, что можно обработать этот экзепшн в (
try/ catch (...)) в вызывающей программе (коде, что вызывает функцию ДЛЛ).

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

Кто прав?
Спасибо за "судейство" ;)))
Посмотрите статейку (link inside). Как раз про обработку исключений. 03.10.04 13:22  
Автор: Den <Denis> Статус: The Elderman
<"чистая" ссылка>


Централизованная обработка исключений
[C++] Предлагаю подвести черту. 16.08.04 02:42  
Автор: void <Grebnev Valery> Статус: Elderman
<"чистая" ссылка>
Не бейте, ежеле опять скажу ламерство… Перед вердиктом:

Killer, конечно же прав, на мой взгляд, когда он говорит, что в большинстве случаев программируя на С++ легко перехватить и обработать экзепшн (что происходит внутри DLL) в вызывающем коде. Хотел, бы отметить, то, что в первом посте было написано – В ОБЩЕМ СЛУЧАЕ (т.е. всегда) НЕВОЗМОЖНО. Т.е. в большинстве случаев (особенно, если программируется всё в одной среде – и DLL, и вызывающий код), таки да… Всё перехватывается и ловится.

Но вот, ниже, пример хакания самого себя в особо извращённой форме в DLL:

//простая функция DLL, где екзепшн связан с обращением к не проинициализированному указателю
// except.dll

#define EXCEPT_API extern "C" __declspec(dllexport)

EXCEPT_API int __stdcall fexcept( void )
{
int rc;
char * s;

memset( s, 0, 1024 );
rc = atoi(s);

return rc;
}

В консольном приложении test.exe эта функция DLL вызывается, как:

// test.exe
typedef int (__stdcall *pEXCEPT_FUN) ( void );

try
{
pfunc();
}
catch(...)
{
_tprintf(_TEXT("Good. We are in catch (...)\n"));
FreeLibrary(hlib);
return;
}

Если и except.dll, и test.exe изготовлены в одной IDE – проблем не возникает.
Особенно не возникает проблем, если это VS.NET.2003. В этом случае, исключительная ситуация (просто очень исключительная в данном случае) в except.dll отлавливается в test.exe – всё работает нормально.

Но!
1) Если скомпилировать except.dll ( release ) в Borland C++ Builder 6.0, a test.exe в VS.NET 2003 – то test.exe _ПРОСТО_МОЛЧАЛИВО_УМИРАЕТ при вызове pfunc(). Даже диалога о недопустимости операций не покажется.
2) Поведение вызывающей программы test.exe зависит не только от того, каким компиллером собрана except.dll, но и с какими опциями – DEBUG, или RELEASE. Впрочем, поведение test.exe будет также зависеть от и опций проекта самого test.exe. (DEBUG, или RELEASE). Может и по неопытности, но я натыкался давно (конечно же в других программах), когда в DEBUG всё работало, а в RELEASE – валилось приложение…

И последнее…. DLL может быть вызвана не только из программы, написанной на С++. Это может быть и VB/VBA. В этом случае описанная «неодинаковость» обработки исключений при использовании разных компиллеров С++ - усугубляется. Необработанность исключения внутри DLL – почти всегда приводит к анормал терминейшн VBA программы. Хотя возможно, я плохо программрую не только на C++, но и на VB. ;(

Посему, предлагаю вынести (или не вынести) коллективным умом следующий вердикт:

1) Если собираем всё в одном и том же языке программирования и используем одну и туже IDE – то экзепшн отлавливается без проблем.

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

3) Ну и ещё …. В целом предложить товарищу void продолжить изучение мат.части, а на буржуйских девелопперов больше не наезжать. ;))
насчет мат части... 16.08.04 04:38  
Автор: Killer{R} <Dmitry> Статус: Elderman
<"чистая" ссылка>
Нашел вот: http://www.microsoft.com/msj/0197/exception/exception.aspx
Присоединяюсь к Thanks ;) 16.08.04 04:54  
Автор: void <Grebnev Valery> Статус: Elderman
<"чистая" ссылка>
[C++] Thanks! Вот и еще одни мои давние грабли "разъяснили"... 16.08.04 04:31  
Автор: Zef <Alloo Zef> Статус: Elderman
<"чистая" ссылка>
А разве при отлове исключительных ситуаций надо использовать не except блок, а catch? [updated] 15.08.04 15:26  
Автор: Den <Denis> Статус: The Elderman
Отредактировано 15.08.04 15:48  Количество правок: 3
<"чистая" ссылка>
По идее DLL является in-proc сервером, выполняющимся внутри процесса и являет собой набор подпрограмм, которые вызываются и исполняются также, как обычные статически слинкованные с программой процедуры.

Из MSDN:
__try {
    float x, y=0;
    x = 5 / y;        // This exception handled by outer block
    __try {
        x = 0;
        y = 27 / x;   // This exception handled by inner block
    }
    __except( GetExceptionCode() == STATUS_FLOATING_DIVIDE_BY_ZERO) {
        printf("handled by inner block");
    }
}
__except( GetExceptionCode() == STATUS_FLOATING_DIVIDE_BY_ZERO ) {
    printf( "handled by outer block" );
}

---
__try- __except - это сугубо MS-овая конструкция. То есть работает только с VC, если не ошибаюсь. 15.08.04 17:43  
Автор: Ktirf <Æ Rusakov> Статус: Elderman
<"чистая" ссылка>
А родной C++-ной конструкцией является try-catch.
У MS try не обрабатывается в C. Только в C++. Не помню,... 16.08.04 00:31  
Автор: void <Grebnev Valery> Статус: Elderman
<"чистая" ссылка>
> А родной C++-ной конструкцией является try-catch.
У MS try не обрабатывается в C. Только в C++. Не помню, точно, но для С они, кажется, предлагают __try.

А exept - Борланд тоже использует .
Именно так, и называется это SEH - Structured Exception Handling. 16.08.04 02:21  
Автор: Ktirf <Æ Rusakov> Статус: Elderman
<"чистая" ссылка>
Все, вспомнил. SEH встроен в винду, и от компиляторов там если и нужна поддержка, то какая-то минимальная. Так что если вопрос о переносимости не стоит, можно пользоваться SEH, только не мешать его с плюсовыми исключениями.
В общем случае, на данный момент, это действительно невозможно. 15.08.04 14:51  
Автор: Ktirf <Æ Rusakov> Статус: Elderman
Отредактировано 15.08.04 14:52  Количество правок: 1
<"чистая" ссылка>
> Вышел спор. Пока без крови ;))
> Суть такова. Есть ДЛЛ, где криво написана одна из функций.
> Известно, что экзепшн внутри самой функции ДЛЛ не
> обрабатывается. Сорца той ДЛЛ нет, чтобы подправить.
>
> Товарищь утверждает, что можно обработать этот экзепшн в (
> try/ catch (...)) в вызывающей программе (коде, что
> вызывает функцию ДЛЛ).
>
> Мой поинт - это невозможно в общем случае. Надеяться на то,
> что экзепшн будет обработан в вызывающем коде - бэд
> практис.
В общем случае, на данный момент, это действительно невозможно. Теоретически преград к реализации передачи исключений между исполняемыми модулями в общем-то нет, вопрос в корректной реализации раскрутки стека. В общем, я бы подождал еще года два, прежде чем полагаться на эту фичу. Новый GCC и (если меня не глючит) VC 7.1 подобные штуки вроде бы поддерживают.

С идеологической же точки зрения исключения можно и нужно использовать как раз в тех случаях, когда вызванная функция не в состоянии сама справиться с нештатной ситуацией. Надеяться на обработку флага ошибки вместо исключения - плохая практика, и прецедент с operator new это наглядно показал. Если не будет обработано исключение, все упадет. Если не будет обработан флаг ошибки, все начнет работать непредсказуемо. Как программист, я предпочитаю первый вариант.
Согласен. Такая формулировка будет более выдержанной и... 16.08.04 01:04  
Автор: void <Grebnev Valery> Статус: Elderman
<"чистая" ссылка>
>Теоретически преград к реализации передачи
> исключений между исполняемыми модулями в общем-то нет,
> вопрос в корректной реализации раскрутки стека.

Согласен. Такая формулировка будет более выдержанной и толковой, чем моя.

> Надеяться на обработку флага ошибки вместо исключения -
> плохая практика

Но, если есть вылезанная функция ДЛЛ, что возвращает HRESULT-код, то почему не ограничиться только анализом этого в вызывающем коде?
Мы ж не анализируем в ТРАЙ/КЭТЧ блоке результаты методов КОМ. Почти всегда идет анализ ! FAILED( rc ), или S_OK.
Похоже, вы не в курсе про историю с оператором new. 16.08.04 02:39  
Автор: Ktirf <Æ Rusakov> Статус: Elderman
<"чистая" ссылка>
> Но, если есть вылезанная функция ДЛЛ, что возвращает
> HRESULT-код, то почему не ограничиться только анализом
> этого в вызывающем коде?
> Мы ж не анализируем в ТРАЙ/КЭТЧ блоке результаты методов
> КОМ. Почти всегда идет анализ ! FAILED( rc ), или S_OK.
Между прочим, это форменное безобразие. Это прогулка по тем же граблям, что и с оператором new, про историю о котором, вы, видимо, все же не в курсе.

История следующая: поначалу operator new, в стиле malloc, при недостатке памяти возвращал 0. Все бы хорошо, вот только большинство программистов на проверку возвращаемого указателя на ноль попросту забивало. Нетрудно догадаться, что после этого в лучшем случае происходила попытка разыменования нулевого указателя, в худшем - неопределенное поведение. В связи с этим в стандарте 98-года (а может быть, и в предыдущем, не помню) прописано, что operator new при недостатке памяти выбрасывает исключение, а ноль возвращает специальная (nothrow)-версия.

Возвращаемые значения очень легко забыть проверить. Особенно если вы сначала пишете return <вызов функции> в расчете на то, что if (!FAILED(rc)) написано в вызывающей функции (ведь так не хочется дорисовывать лишнюю проверку). А потом <вызов функции> в порядке развития функциональности перемещается в тело функции, а if (!FAILED(rc)) по забывчивости так и не появляется.
Признаюсь, не знал. Всегда проверял на нулевое значение... 16.08.04 02:58  
Автор: void <Grebnev Valery> Статус: Elderman
<"чистая" ссылка>
>Нетрудно догадаться,
> что после этого в лучшем случае происходила попытка
> разыменования нулевого указателя, в худшем - неопределенное
> поведение. В связи с этим в стандарте 98-года (а может
> быть, и в предыдущем, не помню) прописано, что operator new
> при недостатке памяти выбрасывает исключение, а ноль
> возвращает специальная (nothrow)-версия.

Признаюсь, не знал. Всегда проверял на нулевое значение. Спасибо за инфу.
Вообще-то можно.. 15.08.04 05:02  
Автор: Killer{R} <Dmitry> Статус: Elderman
<"чистая" ссылка>
По кр. мере под виндой. При исключении управление передается по указателю по fs:0 и в принципе пофиг кто его туда поставил - вызывающая прога или длл. Другой вопрос насколько это красиво так делать.. и вообще насколько красиво жизненная необходимость обработки исключений в рабочей проге... Писать надо так чтобы исключения не возникали, во первых это некоторый оверхед на вызов обработчика через кернел (если часто вызывается), во вторых если исключения возникают не по причине какого нить деления на 0 а например Acess violation то...
Несколько раз натыкался, что исключение внутри ДЛЛ нельзя... 15.08.04 05:49  
Автор: void <Grebnev Valery> Статус: Elderman
<"чистая" ссылка>
> По кр. мере под виндой.
Несколько раз натыкался, что исключение внутри ДЛЛ нельзя было обработать в вызывающем коде.
Поэтому если б речь шла о моём коде, то я привык всё обрабатывать "внутри" самой DLL.
Обработав исключение, записываю текстовую мессагу об ошибке в буфер (если таковая потом понадобится) перед тем, как вернуть из функции DLL код 32-битный ошибки HRESULT.

>При исключении управление
> передается по указателю по fs:0 и в принципе пофиг кто его
> туда поставил - вызывающая прога или длл. Другой вопрос
> насколько это красиво так делать.. и вообще насколько
> красиво жизненная необходимость обработки исключений в
> рабочей проге... Писать надо так чтобы исключения не
> возникали, во первых это некоторый оверхед на вызов
> обработчика через кернел (если часто вызывается), во вторых
> если исключения возникают не по причине какого нить деления
> на 0 а например Acess violation то...

Я пробовал так когда-то очень давно. Не получалось. ;(
Например, функция DLL пытается прочитать "поле" некого рекордсет. А там облом ... Если это не обработать в ДЛЛ, так я даже в "кетч" блок не попадал из "трай". ;(
Наверное, неправильно программировал.
1




Rambler's Top100
Рейтинг@Mail.ru


  Copyright © 2001-2024 Dmitry Leonov   Page build time: 0 s   Design: Vadim Derkach