我现在正在使用libjpeg来保存 JPEG 图像。如果出现错误,libjpeg 的默认行为是调用exit()
,我想避免这种情况,因为这对我的程序来说不是致命错误。libjpeg允许您使用自己的错误管理器,并规定如果您使用自己的error_exit()
函数(exit()
默认调用),则不得将控制权返回给调用者。libjpeg 建议使用setjmp.h而不是程序来满足此要求exit()
。
但是,我正在编写一个 C++ 程序,并且可以访问异常。这个问题的答案表明从回调中抛出异常是安全的(就像在明确定义的行为中一样)。但它没有提到动态库,并且有一个一般的经验法则,即不要跨动态库边界抛出异常。
这是一个例子:
#include <iostream>
#include <jpeglib.h>
#include <cstdio>
#include <stdexcept>
static void handleLibJpegFatalError(j_common_ptr cinfo)
{
(*cinfo->err->output_message)(cinfo);
throw std::runtime_error("error in libjpeg, check stderr");
}
int main()
{
struct jpeg_compress_struct cinfo;
struct jpeg_error_mgr jerr;
FILE* file = std::fopen("out.jpeg", "wb"); // assume this doesn't fail for this example
try
{
cinfo.err = jpeg_std_error(&jerr);
jerr.error_exit = handleLibJpegFatalError;
// let's say this triggers a fatal error in libjpeg and handleLibJpegFatalError() is called
// by libjpeg
jpeg_create_compress(&cinfo);
}
catch (...)
{
std::cerr << "Error saving the JPEG!\n";
}
jpeg_destroy_compress(&cinfo);
std::fclose(file);
}
我想知道的是:即使 libjpeg 被编译为动态库,我是否可以从此回调中抛出异常并将其捕获回我的应用程序中?libjpeg 可能是静态库或动态库,如果它是动态库,则可能使用不同的编译器构建。但是,抛出和捕获异常的代码肯定会在同一个编译单元中。上面的代码安全吗?
仅供参考,我正在为 OS X 和 Windows 开发(并牢记 Linux 的未来可能性),所以我更感兴趣的是,这是否被认为是一般定义明确的行为,而不是针对特定平台/编译器。