libjpeg中的错误处理

Did*_*era 15 c++ libjpeg

我正在使用C++ JPEG库(libjpeg),我意识到当某些函数失败时,调用exit()并关闭应用程序.如何覆盖此行为并阻止应用程序关闭libjpeg错误?

zak*_*ter 20

这是默认行为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);

}
Run Code Online (Sandbox Code Playgroud)

然后使用注册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;
}
Run Code Online (Sandbox Code Playgroud)

你可以在这里找到一个完整的例子.

  • @philix 从三星 Galaxy 加载运动全景图。他们完蛋了。:D (2认同)

Mar*_*ger 8

由于问题是针对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 ...
}
Run Code Online (Sandbox Code Playgroud)

用它:

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
}
Run Code Online (Sandbox Code Playgroud)

  • 我同意,这并不意味着你应该,我只是意味着你可以.此外:基本上跳转可能会导致与异常相同的潜在问题,通常不为C++程序员所熟知,甚至还有更多风险:他们很容易搞砸你的RAII.来自www.cplusplus.com:"在C++中,实现可能执行堆栈展开,它会自动销毁对象.如果这会调用任何非平凡的析构函数,则会导致未定义的行为." 谷歌造型指南btw还提到所有这些规则都有例外,特别是在使用图书馆时. (2认同)
  • 如果调用**libjpeg的代码**是C++,则可以在调用libjpeg的代码中使用RAII创建所有类型的资源. (2认同)

Arn*_*age 5

使用 c++11 我使用 lambda 实现了这个(类似于 Marco 的答案):

[](j_common_ptr cinfo){throw cinfo->err;}
Run Code Online (Sandbox Code Playgroud)

效果很好。只有这样才能抓住'struct jpeg_error_mgr *err'

IE

struct jpeg_error_mgr jerr_mgr;
cinfo.err = jpeg_std_error(&jerr_mgr);
jerr_mgr.error_exit = [](j_common_ptr cinfo){throw cinfo->err;};
Run Code Online (Sandbox Code Playgroud)

   try
   {
      jpeg_create_decompress(&cinfo);

      ...
   }
   catch (struct jpeg_error_mgr *err)
    {
        char pszErr[1024];
        (cinfo.err->format_message)((j_common_ptr)&cinfo, pszErr);

         ...
    }
Run Code Online (Sandbox Code Playgroud)