Question

I am using the C++ JPEG library (libjpeg) and I have realized that when some functions fail exit() is called and the application is closed. How can I override this behavior and prevent the application from closing on libjpeg errors?

Was it helpful?

Solution

This is the default behavior of libjpeg. In order to handle errors with libjpeg, you'll have to define an error handling routine like this:

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);

}

And then register it using 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;
}

You can find a complete example here.

OTHER TIPS

As the question was targetting C++, an alternative approach with exceptions:

Error handler:

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 ...
}

Use it:

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
}

Using c++11 I implemented this using a lambda (similar to Marco's answer):

[](j_common_ptr cinfo){throw cinfo->err;}

which works well. Only then catch on 'struct jpeg_error_mgr *err'

i.e.

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

and

   try
   {
      jpeg_create_decompress(&cinfo);

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

         ...
    }
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top