The OpenNET Project / Index page

[ новости /+++ | форум | теги | ]

форумы  помощь  поиск  регистрация  майллист  ВХОД  слежка  RSS
"Использование C библиотек в C++ - обработка ошибок"
Вариант для распечатки  
Пред. тема | След. тема 
Форумы Программирование под UNIX (Public)
Изначальное сообщение [Проследить за развитием треда]

"Использование C библиотек в C++ - обработка ошибок"  
Сообщение от AMDmi3 on 04-Июн-06, 04:59 
Использую C библиотеки в программе на C++. Распространенный механизм обработки ошибок (как в libjpeg, libpng, libcurl) - использование setjmp и задание callback функции, которая вызывается в случае ошибки и делает longjmp. Не могу понять, что делать в C++ - longjmp там использовать, насколько я понимаю, нельзя, а исключения брошенные в callback функции, вызываемой через C, не ловятся. Вот примеры кода:

/* c исключениями */

class my_oo_wrapper {
   static void error_callback();
   void load();
}

my_oo_wrapper::error_callback() {
  throw "there was an error :(";
}

my_oo_wrapper::load() {
  c_lib_handle h;

  c_lib_init(h);
  c_lib_set_error_callback(h, error_callback);

  try {
    c_lib_do_stuff(h); // тут происходит ошибка, вызывается error_callback
  } catch (char* e) {
    // но тут мы ничего не словим, исключение сразу попадет на самый верх в terminate()
    /* чистка мусора */
  }
}

/* c setjmp */

class my_oo_wrapper {
   static void error_callback();
   void load();
}

my_oo_wrapper::error_callback(*some_data) {
  // я думаю так делать нельзя, потому что ЭТА функция статическая
  // или можно?
  longjmp(some_data->jmpbuf, 1);
}

my_oo_wrapper::load() {
  c_lib_handle h;

  if (setjmp()) {
    // сюда попадем вызвав longjmp
    /* чистка мусора */
    return;
  }

  c_lib_init(h);
  c_lib_set_error_callback(h, error_callback);

  c_lib_do_stuff(h); // тут происходит ошибка, вызывается error_callback
}

Правка | Высказать мнение | Ответить | Cообщить модератору | Наверх

 Оглавление

Сообщения по теме [Сортировка по времени, UBB]


1. "Использование C библиотек в C++ - обработка ошибок"  
Сообщение от ACCA (ok) on 04-Июн-06, 10:16 
Особого смысла втаскивать error_callback внутрь класса my_oo_wrapper нету - статические функции могут лазить только по статическим членам класса. В остальном всё вроде по-пацански.

Единственный вопрос - как именно ты надеешься сделать "чистку мусора". Вариантов там, мягко говоря, до хрена.

Правка | Высказать мнение | Ответить | Cообщить модератору | Наверх

2. "Использование C библиотек в C++ - обработка ошибок"  
Сообщение от AMDmi3 email on 04-Июн-06, 15:13 
>Особого смысла втаскивать error_callback внутрь класса my_oo_wrapper нету - статические функции могут
>лазить только по статическим членам класса. В остальном всё вроде по-пацански.
>Единственный вопрос - как именно ты надеешься сделать "чистку мусора". Вариантов там,
>мягко говоря, до хрена.
Так в том-то и проблема в том что оба способа не работают. Мне, грубо говоря, после вызова error_callback нужно попасть обратно в my_oo_wrapper::load, 2 способами что мне пришли в голову сделать это нельзя. Или единственный вариант - полностью вытащить работу с библиотеками из класса?
Правка | Высказать мнение | Ответить | Cообщить модератору | Наверх

3. "Использование C библиотек в C++ - обработка ошибок"  
Сообщение от AMDmi3 email on 04-Июн-06, 15:24 
>Особого смысла втаскивать error_callback внутрь класса my_oo_wrapper нету - статические функции могут
>лазить только по статическим членам класса. В остальном всё вроде по-пацански.
>
>
>Единственный вопрос - как именно ты надеешься сделать "чистку мусора". Вариантов там,
>мягко говоря, до хрена.

Кстати, насчет setjmp - я прав в том, что тут его применять нельзя? Мне уже начинает казаться что можно - ведь из ::load() мы еще не вышли - все ее структуры есть в стеке, включая this, и то что делаем мы longjmp из статической функции класса (либо вообще из левой функции) ничего не значит.

Правка | Высказать мнение | Ответить | Cообщить модератору | Наверх

4. "Использование C библиотек в C++ - обработка ошибок"  
Сообщение от michelnok (??) on 04-Июн-06, 19:07 
>исключения брошенные в callback функции, вызываемой через C, не ловятся

А можно про это подробнее?

Правка | Высказать мнение | Ответить | Cообщить модератору | Наверх

5. "Использование C библиотек в C++ - обработка ошибок"  
Сообщение от michelnok (??) on 04-Июн-06, 20:18 
>>исключения брошенные в callback функции, вызываемой через C, не ловятся
>
>А можно про это подробнее?

Хех. Проверил. Действительно не ловятся :(
Могу посоветовать только грустное решение с обертками вокруг вызываемых функций. В обертках - setjmp и throw когда результат setjmp не 0, в callback'ах - longjmp.

А longjmp'ить куда-то в середину C++ кода действительно выглядит некошерно...

Правка | Высказать мнение | Ответить | Cообщить модератору | Наверх

6. "Использование C библиотек в C++ - обработка ошибок"  
Сообщение от AMDmi3 email on 05-Июн-06, 06:16 
>>>исключения брошенные в callback функции, вызываемой через C, не ловятся
>>
>>А можно про это подробнее?
>
>Хех. Проверил. Действительно не ловятся :(
>Могу посоветовать только грустное решение с обертками вокруг вызываемых функций. В обертках
>- setjmp и throw когда результат setjmp не 0, в callback'ах
>- longjmp.
>
>А longjmp'ить куда-то в середину C++ кода действительно выглядит некошерно...

Да, я тоже склоняюсь к такому решению.

Правка | Высказать мнение | Ответить | Cообщить модератору | Наверх

7. "Использование C библиотек в C++ - обработка ошибок"  
Сообщение от AMDmi3 on 05-Июн-06, 19:27 
В общем, сделал штуку довольно срашную, но вроде бы работает.

class my_oo_wrapper {
  static void error_callback();
  void load();
}

void my_oo_wrapper::error_callback(jmpbuf) {
  longjmp(jmpbuf, 1);
}

void my_oo_wrapper::load() {
  c_lib_handle h = 0;

  jmp_buf buf;

  try {
    if (setjmp(buf)) {
      throw error;
    }

    c_lib_init(h);
    c_lib_set_error_callback(h, error_callback, /* передается в callback */ buf);

    c_lib_do_stuff(h); // тут происходит ошибка, вызывается error_callback

    // уборка мусора после нормальной работы
    c_lib_cleanup(h);
  } catch(...) {
    // уборка мусора после ошибки - причем только тех объектов что были инициализированы
    if(h)
      c_lib_cleanup(h);

    throw;
  }
}

Правка | Высказать мнение | Ответить | Cообщить модератору | Наверх

8. "Использование C библиотек в C++ - обработка ошибок"  
Сообщение от michelnok (??) on 06-Июн-06, 17:57 
>В общем, сделал штуку довольно срашную, но вроде бы работает.
>    c_lib_do_stuff(h); // тут происходит ошибка, вызывается error_callback

А если этот вызов будет глубже (не в той функции где setjmp), что будет с деструкторами локальных объектов C++? 100% не вызовутся...

Правка | Высказать мнение | Ответить | Cообщить модератору | Наверх

9. "Использование C библиотек в C++ - обработка ошибок"  
Сообщение от AMDmi3 on 06-Июн-06, 18:57 
>>В общем, сделал штуку довольно срашную, но вроде бы работает.
>>    c_lib_do_stuff(h); // тут происходит ошибка, вызывается error_callback
>
>А если этот вызов будет глубже (не в той функции где setjmp),
>что будет с деструкторами локальных объектов C++? 100% не вызовутся...

Не понял.
error_callback может быть вызван только из того, что вызывается в try-блоке в ::load после setjmp(). Если мы создаем объекты в try блоке, и выпадаем, то в catch мы их, соответственно, удалим. А внутри c_lib_* только чистый C, она чистит свои потроха при вызове c_lib_cleanup.

Правка | Высказать мнение | Ответить | Cообщить модератору | Наверх

Архив | Удалить

Индекс форумов | Темы | Пред. тема | След. тема
Оцените тред (1=ужас, 5=супер)? [ 1 | 2 | 3 | 4 | 5 ] [Рекомендовать для помещения в FAQ]




Партнёры:
PostgresPro
Inferno Solutions
Hosting by Hoster.ru
Хостинг:

Закладки на сайте
Проследить за страницей
Created 1996-2025 by Maxim Chirkov
Добавить, Поддержать, Вебмастеру