Я использую библиотеку C++ JPEG (libjpeg), и я понял, что когда некоторые функции сбой вызывается exit() и приложение закрывается. Как я могу отменить это поведение и предотвратить закрытие приложения при ошибках libjpeg?Обработка ошибок в libjpeg
ответ
Это поведение по умолчанию libjpeg
. Для того, чтобы обрабатывать ошибки с libjpeg, вы должны определить процедуру обработки ошибок в так:
struct jpegErrorManager {
/* "public" fields */
struct jpeg_error_mgr pub;
/* for return to caller */
jmp_buf setjmp_buffer;
};
char jpegLastErrorMsg[JMSG_LENGTH_MAX];
void jpegErrorExit (j_common_ptr cinfo)
{
/* cinfo->err actually points to a jpegErrorManager struct */
jpegErrorManager* myerr = (jpegErrorManager*) cinfo->err;
/* note : *(cinfo->err) is now equivalent to myerr->pub */
/* output_message is a method to print an error message */
/*(* (cinfo->err->output_message)) (cinfo);*/
/* Create the message */
(*(cinfo->err->format_message)) (cinfo, jpegLastErrorMsg);
/* Jump to the setjmp point */
longjmp(myerr->setjmp_buffer, 1);
}
А затем зарегистрировать его с помощью jpeg_std_error
.
FILE* fileHandler;
/* ... */
struct jpeg_decompress_struct cinfo;
jpegErrorManager jerr;
cinfo.err = jpeg_std_error(&jerr.pub);
jerr.pub.error_exit = jpegErrorExit;
/* Establish the setjmp return context for my_error_exit to use. */
if (setjmp(jerr.setjmp_buffer)) {
/* If we get here, the JPEG code has signaled an error. */
cerr << jpegLastErrorMsg << endl;
jpeg_destroy_decompress(&cinfo);
fclose(fileHandler);
return 1;
}
Вы можете найти полный пример here.
Поскольку вопрос был ориентируетесь C++, альтернативный подход, с исключениями:
обработчик ошибок:
void jpegErrorExit (j_common_ptr cinfo)
{
char jpegLastErrorMsg[JMSG_LENGTH_MAX];
/* Create the message */
(*(cinfo->err->format_message)) (cinfo, jpegLastErrorMsg);
/* Jump to the setjmp point */
throw std::runtime_error(jpegLastErrorMsg); // or your preffered exception ...
}
Использование:
FILE* fileHandler;
/* ... */
struct jpeg_decompress_struct cinfo;
struct jpeg_error_mgr jerr;
cinfo.err = jpeg_std_error(&jerr);
jerr.error_exit = jpegErrorExit;
try {
jpeg_create_decompress(&cinfo);
jpeg_stdio_src(&cinfo, fileHandler);
/// ...
jpeg_destroy_decompress(&cinfo);
fclose(fileHandler);
}
catch (std::runtime_exception & e) {
jpeg_destroy_decompress(&cinfo);
fclose(fileHandler);
throw; // or return an error code
}
Спасибо за ваш комментарий. Я думаю, что интересно отметить, что C++ не означает, что мы должны использовать исключения. Фактически, стиль кодирования Google C++ гласит: «Мы не используем исключения» и не более :-) –
Я согласен, это не значит, что вы должны, я просто хочу, чтобы вы могли. Кроме того: в основном прыжки могут вызывать те же потенциальные проблемы, что и исключения, обычно не известны программистам на С ++, и даже могут быть еще более опасны: они могут легко испортить ваш RAII. От www.cplusplus.com: «В C++ реализация может выполнять раскрутку стека, которая уничтожает объекты с автоматической продолжительностью. Если это вызывает любые нетривиальные деструкторы, это приводит к неопределенному поведению». И руководство по стилю Google также упоминает, что существуют исключения для всех этих правил, особенно когда используются библиотеки. –
Но libjpeg - это C, а не C++, поэтому у него нет деструкторов, нетривиальных или других, с которыми запутался setjmp/longjmp. –
Использование C++ 11 Я реализовал это с помощью лямбда (по аналогии с ответом Марко):
[](j_common_ptr cinfo){throw cinfo->err;}
который работает хорошо. Только тогда зацепиться 'структура jpeg_error_mgr * ERR'
т.е.
struct jpeg_error_mgr jerr_mgr;
cinfo.err = jpeg_std_error(&jerr_mgr);
jerr_mgr.error_exit = [](j_common_ptr cinfo){throw cinfo->err;};
и
try
{
jpeg_create_decompress(&cinfo);
...
}
catch (struct jpeg_error_mgr *err)
{
char pszErr[1024];
(cinfo.err->format_message)((j_common_ptr)&cinfo, pszErr);
...
}
Спасибо так много, дайте мне попробовать, и я вам скажу :) –
Вау, Я не думал об этих механизмах прыжка. Большое вам спасибо, это сработало! –
Вы можете попробовать C++ lambda с исключениями для создания обработчика исключений inline - см. Мой ответ http://stackoverflow.com/a/34351005/1151329 –