Если вы используете gcc 4.4.7 (и выше) на x86-64 linux , с dwarf механизмом обработки исключений (который может быть по умолчанию) один), у меня есть способ решить это.
Предположим, что ваш встроенный код сборки является функцией inline_add
. Он вызовет другую функцию add
, которая может вызвать исключение. Вот код:
extern "C" int add(int a, int b) {
throw "in add";
}
int inline_add(int a, int b) {
int r = 0;
__asm__ __volatile__ (
"movl %1, %%edi\n\t"
"movl %2, %%esi\n\t"
"call add\n\t"
"movl %%eax, %0\n\t"
:"=r"(r)
:"r"(a), "r"(b)
:"%eax"
);
return r;
}
Если вы позвоните inline_add
, как это:
try {
inline_add(1, 1);
} catch (...) {
std::cout << "in catch" << std::endl;
}
произойдет сбой, потому что gcc не предоставляет рамку исключения для inline_add
. Когда дело доходит до исключения, оно должно взломать. (см. здесь для «Совместимости с C»)
Так что нам нужно подделать для него фрейм исключения, но было бы трудно взломать сборку gcc, мы просто используем функции с соответствующим фреймом исключения, чтобы окружить его
мы определяем функцию следующим образом:
void build_exception_frame(bool b) {
if (b) {
throw 0;
}
}
и позвоните inline_add
вот так:
try {
inline_add(1, 1);
build_exception_frame(false);
} catch (...) {
std::cout << "in catch" << std::endl;
}
и это просто работает.
build_exception_frame
должен прийти после звонка, иначе он не будет работать
Более того, чтобы оптимизация gcc не приняла build_exception_frame
, нам нужно добавить следующее:
void build_exception_frame(bool b) __attribute__((optimize("O0")));
Вы можете проверить код сборки, сгенерированный gcc, для проверки кода.
Кажется, что gcc предоставляет фрейм исключений для всего try
/ catch
, если есть одна функция, которая может выдать, и положение имеет значение.
Нужно посмотреть, как gcc работает над этим позже.
Если кто-нибудь знает об этом, пожалуйста, будьте любезны, дайте мне знать. Спасибо.