Освобождение ресурсов & обработка ошибок
От:
Аноним
Дата: 04.08.06 03:28
Оценка:
Вот такая ситуация
HANDLE h1 = Somefunc1();
if (h1 == NULL) return ERROR_CODE;
HANDLE h2 = Somefunc2();
if (h2 == NULL) {
CloseHandle(h2);
return ERROR_CODE;
}
HANDLE h3 = Somefunc3();
if (h3 == NULL) {
CloseHandle(h1);
CloseHandle(h2);
return ERROR_CODE;
}
HANDLE h4 = Somefunc4();
if (h3 == NULL) {
CloseHandle(h1);
CloseHandle(h2);
CloseHandle(h3);
return ERROR_CODE;
}
if (Condition1) {
DoSomething();
CloseHandle(h1);
CloseHandle(h2);
CloseHandle(h3);
return OK_1;
}
if (Condition2) {
DoSomething();
CloseHandle(h1);
CloseHandle(h2);
CloseHandle(h3);
return OK_2;
}
//...
CloseHandle(h1);
CloseHandle(h2);
CloseHandle(h3);
return OK_7;
Как можно избавиться от таких вещей ?
CloseHandle(h1);
CloseHandle(h2);
CloseHandle(h3);
return OK_1;
В принципе можно было бы 1 раз в конце написать, а во всех остальных местах делать "goto". Но это как то некрасиво. А писать каждый раз полностью тоже некрасиво, да и запутаешься потом...
Re: Освобождение ресурсов & обработка ошибок
Здравствуйте, Аноним, Вы писали:
А>Вот такая ситуация
А>Как можно избавиться от таких вещей ?
А>А> CloseHandle(h1);
А> CloseHandle(h2);
А> CloseHandle(h3);
А> return OK_1;
А>
А>В принципе можно было бы 1 раз в конце написать, а во всех остальных местах делать "goto". Но это как то некрасиво. А писать каждый раз полностью тоже некрасиво, да и запутаешься потом...
а С или С++ ?
если С++ то можно так —
struct handle_holder
{
HANDLE handle_;
handle_holder( HANDLE h ) : handle_(h) {}
bool operator ! () const
{
return (!handle_);
}
HANDLE value() const
{
return handle_;
}
~handle_holder()
{
CloseHandle( handle_ );
}
};
// использовать так -
{
handle_holder h1( SomeFunc1() );
if ( !h1 )
return SOME_ERROR_1;
}
при этом для всех хендлов будет вызван CloseHandle() автоматом при выходе из функции.
Re: Освобождение ресурсов & обработка ошибок
От:
Jonathan
Дата: 04.08.06 03:41
Оценка:
используй идею auto_ptr
"If everything seems under control, you're just not going fast enough"
Re: Освобождение ресурсов & обработка ошибок
От:
_Dreamer
Дата: 04.08.06 03:46
Оценка:
Re: Освобождение ресурсов & обработка ошибок
От:
avs99
Дата: 04.08.06 03:46
Оценка:
См. в сторону RAII (resource acquisition is initialization).
class CHandle
{
public :
CHandle(HANDLE h): m_Handle(h) {};
~CHandle()
{
if (m_Handle != NULL)
CloseHandle(m_Handle);
}
.... // ну и всякого тут по желанию, HANDLE operator() и т.д.
}
CHandle h1( Somefunc1() );
CHandle h2( Somefunc2() );
Здравствуйте, Аноним, Вы писали:
А>Вот такая ситуация
А>А>HANDLE h1 = Somefunc1();
А>if (h1 == NULL) return ERROR_CODE;
А>HANDLE h2 = Somefunc2();
А>if (h2 == NULL) {
А> CloseHandle(h2);
А> return ERROR_CODE;
А>}
А>HANDLE h3 = Somefunc3();
А>if (h3 == NULL) {
А> CloseHandle(h1);
А> CloseHandle(h2);
А> return ERROR_CODE;
А>}
А>HANDLE h4 = Somefunc4();
А>if (h3 == NULL) {
А> CloseHandle(h1);
А> CloseHandle(h2);
А> CloseHandle(h3);
А> return ERROR_CODE;
А>}
А>if (Condition1) {
А> DoSomething();
А> CloseHandle(h1);
А> CloseHandle(h2);
А> CloseHandle(h3);
А> return OK_1;
А>}
А>if (Condition2) {
А> DoSomething();
А> CloseHandle(h1);
А> CloseHandle(h2);
А> CloseHandle(h3);
А> return OK_2;
А>}
А>//...
А>CloseHandle(h1);
А>CloseHandle(h2);
А>CloseHandle(h3);
А>return OK_7;
А>
А>Как можно избавиться от таких вещей ?
А>А> CloseHandle(h1);
А> CloseHandle(h2);
А> CloseHandle(h3);
А> return OK_1;
А>
А>В принципе можно было бы 1 раз в конце написать, а во всех остальных местах делать "goto". Но это как то некрасиво. А писать каждый раз полностью тоже некрасиво, да и запутаешься потом...
Re[2]: Освобождение ресурсов & обработка ошибок
От:
Аноним
Дата: 04.08.06 04:15
Оценка:
Здравствуйте, _Dreamer, Вы писали:
_D>а С или С++ ?
_D>если С++ то можно так -
_D>_D>struct handle_holder
_D>{
_D> HANDLE handle_;
_D> handle_holder( HANDLE h ) : handle_(h) {}
_D> bool operator ! () const
_D> {
_D> return (!handle_);
_D> }
_D> HANDLE value() const
_D> {
_D> return handle_;
_D> }
_D> ~handle_holder()
_D> {
_D> CloseHandle( handle_ );
_D> }
_D>};
_D>// использовать так -
_D>{
_D> handle_holder h1( SomeFunc1() );
_D> if ( !h1 )
_D> return SOME_ERROR_1;
_D>}
_D>
_D>при этом для всех хендлов будет вызван CloseHandle() автоматом при выходе из функции.
Пасиб, понял.
Re: Освобождение ресурсов & обработка ошибок
От:
sokel
Дата: 04.08.06 07:02
Оценка:
Можно так:
HANDLE h1, h2, h3, h4;
h1 = h2 = h3 = h4 = NULL;
int ret = ERROR_CODE;
if ((h1 = SomeFunc1()) && (h2 = SomeFunc2()) && (h3 = SomeFunc3()) && (h4 = SomeFunc4()))
{
if (Condition1) { DoSomething(); ret = OK_1; }
else if (Condition2) { DoSomething(); ret = OK_2; }
//..
else ret = OK_7;
}
if (h1)CloseHandle(h1);
if (h2)CloseHandle(h2);
if (h3)CloseHandle(h3);
if (h4)CloseHandle(h4);
return ret;
Re: Освобождение ресурсов & обработка ошибок
От:
Testus
Дата: 04.08.06 07:12
Оценка:
Можно упростить это всё дело с использованием обработчика исключительных ситуаций
__try
{
//делать "опасные" действия
}
__except
{
//тут можно обработать ошибки
}
P.S. Винда такое часто использует
Glück auf
Re[2]: Освобождение ресурсов & обработка ошибок
Здравствуйте, Testus, Вы писали:
T>Можно упростить это всё дело с использованием обработчика исключительных ситуаций
T>__try
T>__except
А try/catch???
До последнего не верил в пирамиду Лебедева.
Re[2]: Освобождение ресурсов & обработка ошибок
От:
Left2
Дата: 04.08.06 08:07
Оценка:
Настоятельно рекомендовал бы юзать такие конструкции как можно реже.
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Re[3]: Освобождение ресурсов & обработка ошибок
От:
Testus
Дата: 04.08.06 08:45
Оценка:
Здравствуйте, Left2, Вы писали:
L>Настоятельно рекомендовал бы юзать такие конструкции как можно реже.
Почему?
Glück auf
Re[3]: Освобождение ресурсов & обработка ошибок
От:
Testus
Дата: 04.08.06 09:04
Оценка:
Здравствуйте, Roman Odaisky, Вы писали:
RO>Здравствуйте, Testus, Вы писали:
T>>Можно упростить это всё дело с использованием обработчика исключительных ситуаций
T>>__try
T>>__except
А у __try/__except есть еще удобная __finally и __leave, хотя можно и try/catch
Glück auf
Re[4]: Освобождение ресурсов & обработка ошибок
От:
Left2
Дата: 04.08.06 09:13
Оценка:
T>Почему?
1. Непереносимость
2. Невозможность использования внутри __try __catch хоть сколько-либо С++ кода (нет возможности создавать классы с конструкторами-деструкторами.
3. Надо аккуратно сопрягать __try/__catch с родным для С++ try/catch
Вообщем, никаких плюсов по сравнению с try/catch я не вижу кроме тех случаев когда действительно нужно работать с Windows SEH (задача довольно редкая).
Ну и вообще — использовать try/catch для очистки ресуров идеологически неверно, для этого RAII придумали.
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Re[2]: Освобождение ресурсов & обработка ошибок
От:
vvotan
Дата: 05.08.06 13:58
Оценка:
Здравствуйте, Testus, Вы писали:
T>Можно упростить это всё дело с использованием обработчика исключительных ситуаций
Я бы даже сказал:
DWORD Funcarama4() {
// IMPORTANT: Initialize all variables to assume failure.
HANDLE hFile = INVALID_HANDLE_VALUE;
PVOID pvBuf = NULL;
// Assume that the function will not execute successfully.
BOOL fFunctionOk = FALSE;
__try {
DWORD dwNumBytesRead;
BOOL fOk;
hFile = CreateFile("SOMEDATA.DAT" , GENERIC_READ,
FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL);
if (hFile == INVALID_HANDLE_VALUE) {
__leave ;
}
pvBuf = VirtualAlloc(NULL, 1024, MEM_COMMIT, PAGE_READWRITE);
if (pvBuf == NULL) {
__leave ;
}
fOk = ReadFile(hFile, pvBuf, 1024, &dwNumBytesRead, NULL);
if (!fOk || (dwNumBytesRead == 0)) {
__leave ;
}
// Do some calculation on the data.
// Indicate that the entire function executed successfully.
fFunctionOk = TRUE;
}
__finally {
// Clean up all the resources.
if (pvBuf != NULL)
VirtualFree(pvBuf, MEM_RELEASE | MEM_DECOMMIT);
if (hFile != INVALID_HANDLE_VALUE)
CloseHandle(hFile);
}
// Continue processing.
return (fFunctionOk);
}
(с) Рихтер
--
Sergey Chadov
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Re[5]: Освобождение ресурсов & обработка ошибок
От:
vvotan
Дата: 05.08.06 13:58
Оценка:
Здравствуйте, Left2, Вы писали:
T>>Почему?
L>1. Непереносимость
Это по сравнению с CloseHandle?
L>2. Невозможность использования внутри __try __catch хоть сколько-либо С++ кода (нет возможности создавать классы с конструкторами-деструкторами.
Это да. Но если там С++ кода все равно нет, то никто не мешает воспользоваться SEH.
В приведенном примере типичный код общения с винапи(так и вижу открытие файлмаппинга), возможно находящийся внутри С++ класса. В таком случае ничего страшного от использования SEH нету.
L>3. Надо аккуратно сопрягать __try/__catch с родным для С++ try/catch
Это тоже да, в типичном с-подобном коде никаких try/catch нету.
L>Вообщем, никаких плюсов по сравнению с try/catch я не вижу
__finally
L>Ну и вообще — использовать try/catch для очистки ресуров идеологически неверно, для этого RAII придумали.
Задолбешься каждый хендл в класс оборачивать. Для небольшого проекта SEH может оказаться проще.
--
Sergey Chadov
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Re[6]: Освобождение ресурсов & обработка ошибок
Hello vvotan, you wrote:
> Задолбешься каждый хендл в класс оборачивать. Для небольшого проекта SEH может оказаться проще.
А если шаблон сделать? Например, с двумя параметрами: тип дескриптора и указатель на функцию для освобождения ресурса.
--
Всего хорошего, Слава
ICQ: 197577902
Posted via RSDN NNTP Server 2.0
Re[7]: Освобождение ресурсов & обработка ошибок
От:
vvotan
Дата: 05.08.06 17:06
Оценка:
Здравствуйте, Slava Antonov, Вы писали:
SA>Hello vvotan, you wrote:
>> Задолбешься каждый хендл в класс оборачивать. Для небольшого проекта SEH может оказаться проще.
SA>А если шаблон сделать? Например, с двумя параметрами: тип дескриптора и указатель на функцию для освобождения ресурса.
Можно и так
--
Sergey Chadov
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Re: Освобождение ресурсов & обработка ошибок
От:
k732
Дата: 05.08.06 17:48
Оценка:
Здравствуйте, Аноним, Вы писали:
А>Вот такая ситуация
А>А>HANDLE h1 = Somefunc1();
А>if (h1 == NULL) return ERROR_CODE;
А>HANDLE h2 = Somefunc2();
А>if (h2 == NULL) {
А> CloseHandle(h2);
А> return ERROR_CODE;
А>}
А>HANDLE h3 = Somefunc3();
А>if (h3 == NULL) {
А> CloseHandle(h1);
А> CloseHandle(h2);
А> return ERROR_CODE;
А>}
А>HANDLE h4 = Somefunc4();
А>if (h3 == NULL) {
А> CloseHandle(h1);
А> CloseHandle(h2);
А> CloseHandle(h3);
А> return ERROR_CODE;
А>}
А>if (Condition1) {
А> DoSomething();
А> CloseHandle(h1);
А> CloseHandle(h2);
А> CloseHandle(h3);
А> return OK_1;
А>}
А>if (Condition2) {
А> DoSomething();
А> CloseHandle(h1);
А> CloseHandle(h2);
А> CloseHandle(h3);
А> return OK_2;
А>}
А>//...
А>CloseHandle(h1);
А>CloseHandle(h2);
А>CloseHandle(h3);
А>return OK_7;
А>
А>Как можно избавиться от таких вещей ?
А>А> CloseHandle(h1);
А> CloseHandle(h2);
А> CloseHandle(h3);
А> return OK_1;
А>
А>В принципе можно было бы 1 раз в конце написать, а во всех остальных местах делать "goto". Но это как то некрасиво. А писать каждый раз полностью тоже некрасиво, да и запутаешься потом...
#include <boost\shared_ptr.hpp>
class Handle {
private :
boost::shared_ptr<void > m_handle;
public :
Handle ()
{
m_handle = CreateHandleFunction(...);
if (m_handle == INVALID_HANDLE_VALUE)
{
throw ...;
}
}
Handle (HANDLE handle) : m_handle (handle, CloseHandle) {;}
operator HANDLE () { return m_handle.get(); }
};
void main (void )
{
try
{
Handle h = Somefunc2(...);
...
}
catch (...)
{
...
}
}
Re[2]: Освобождение ресурсов & обработка ошибок
От:
k732
Дата: 05.08.06 17:52
Оценка:
Здравствуйте, k732, Вы писали:
K>Здравствуйте, Аноним, Вы писали:
немного ошибся
#include <boost\shared_ptr.hpp>
class Handle {
private :
boost::shared_ptr<void > m_handle;
public :
Handle ()
{
HANDLE handle = CreateHandleFunction(...);
if (handle == INVALID_HANDLE_VALUE)
{
throw ...;
}
m_handle.reset (handle, CloseHandle);
}
Handle (HANDLE handle) : m_handle (handle, CloseHandle) {;}
operator HANDLE () { return m_handle.get(); }
};
void main (void )
{
try
{
Handle h = Somefunc2(...);
...
}
catch (...)
{
...
}
}
Re: Освобождение ресурсов & обработка ошибок
От:
k732
Дата: 07.08.06 08:20
Оценка:
Здравствуйте, Аноним, Вы писали:
А>Вот такая ситуация
А>А>HANDLE h1 = Somefunc1();
А>if (h1 == NULL) return ERROR_CODE;
А>HANDLE h2 = Somefunc2();
А>if (h2 == NULL) {
А> CloseHandle(h2);
А> return ERROR_CODE;
А>}
А>HANDLE h3 = Somefunc3();
А>if (h3 == NULL) {
А> CloseHandle(h1);
А> CloseHandle(h2);
А> return ERROR_CODE;
А>}
А>HANDLE h4 = Somefunc4();
А>if (h3 == NULL) {
А> CloseHandle(h1);
А> CloseHandle(h2);
А> CloseHandle(h3);
А> return ERROR_CODE;
А>}
А>if (Condition1) {
А> DoSomething();
А> CloseHandle(h1);
А> CloseHandle(h2);
А> CloseHandle(h3);
А> return OK_1;
А>}
А>if (Condition2) {
А> DoSomething();
А> CloseHandle(h1);
А> CloseHandle(h2);
А> CloseHandle(h3);
А> return OK_2;
А>}
А>//...
А>CloseHandle(h1);
А>CloseHandle(h2);
А>CloseHandle(h3);
А>return OK_7;
А>
А>Как можно избавиться от таких вещей ?
А>А> CloseHandle(h1);
А> CloseHandle(h2);
А> CloseHandle(h3);
А> return OK_1;
А>
А>В принципе можно было бы 1 раз в конце написать, а во всех остальных местах делать "goto". Но это как то некрасиво. А писать каждый раз полностью тоже некрасиво, да и запутаешься потом...
обернуть все это (я уже где-то приводил этот пример)
#include <boost\shared_ptr.hpp>
class Handle {
private :
boost::shared_ptr<void > m_handle;
public :
Handle ()
{
HANDLE handle = CreateHandleFunction(...);
if (handle == INVALID_HANDLE_VALUE)
{
throw ...;
}
m_handle.reset (handle, CloseHandle);
}
Handle (HANDLE handle) : m_handle (handle, CloseHandle) {;}
operator HANDLE () { return m_handle.get(); }
};
void main (void )
{
try
{
Handle h = Somefunc(...);
...
}
catch (...)
{
...
}
}
или просто, нужно закрыть копирующие конструкторы
class Handle {
private :
HANDLE m_handle;
Handle (const Handle&);
Handle& operator = (const Handle&);
public :
Handle ()
{
m_handle = CreateHandleFunction(...);
if (m_handle == INVALID_HANDLE_VALUE)
{
throw ...;
}
}
~Handle () { CloseHandle(m_handle); }
Handle (HANDLE handle) : m_handle (handle) {;}
operator HANDLE () { return m_handle; }
};
Пока на собственное сообщение не было ответов, его можно удалить.
Удалить