Генерация исключения в C++ в обратном вызове C, возможное пересечение границы динамической библиотеки… безопасно ли это?

Прямо сейчас я использую libjpegдля сохранения изображений в формате JPEG. Если есть ошибка, libjpeg по умолчанию вызывает exit(), чего я хочу избежать, поскольку это не фатальная ошибка для моей программы. libjpeg позволяет вам использовать собственный менеджер ошибоки требует, чтобы при использовании собственной функции error_exit()(которая по умолчанию вызывает exit()) вы не долженне возвращать управление вызывающей стороне. libjpeg предлагает использовать setjmp.hдля выполнения этого требования, а не exit()программу.

Однако я пишу программу на C++ и имею доступ к исключениям. В ответе на этот вопросговорится, что безопасно (как и при четко определенном поведении) генерировать исключение из обратного вызова. Но в нем не упоминаются динамические библиотеки, и существует общее практическое правило: вы не создаете исключения за пределами границ динамической библиотеки.

Вот пример:

#include 
#include 
#include 
#include 

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), поэтому меня больше интересует, известно ли это как четко определенное поведение в целом, а не для конкретной платформы/компилятора.

15
задан Community 23 May 2017 в 12:24
поделиться