Я имею, некоторые нечетные сам изменяющий код, но в корне его являются довольно простой проблемой: Я хочу смочь выполнить a jmp
(или a call
) и затем от той произвольной точки выдают исключение и поймали его блоком попытки/выгоды, который содержал jmp
/call
.
Но когда я делаю это (в gcc 4.4.1 x86_64) результаты исключения в a terminate()
поскольку это было бы, если исключение было выдано от за пределами попытки/выгоды. Я действительно не вижу, как это отличается, чем выдача исключения изнутри некоторой обширной библиотеки, все же это, очевидно - потому что это просто не работает.
Как я могу выполнить a jmp
или call
но все еще отбросьте исключение назад к исходной попытке/выгоде? Почему эта попытка/выгода не продолжает обрабатывать эти исключения, как она была бы, если функция обычно вызывалась?
Код:
#include <iostream>
#include <stdexcept>
using namespace std;
void thrower()
{
cout << "Inside thrower" << endl;
throw runtime_error("some exception");
}
int main()
{
cout << "Top of main" << endl;
try {
asm volatile (
"jmp *%0" // same thing happens with a call instead of a jmp
:
: "r"((long)thrower)
:
);
} catch (exception &e) {
cout << "Caught : " << e.what() << endl;
}
cout << "Bottom of main" << endl << endl;
}
Ожидаемый вывод:
Top of main
Inside thrower
Caught : some exception
Bottom of main
Эффективная выходная мощность:
Top of main
Inside thrower
terminate called after throwing an instance of 'std::runtime_error'
what(): some exception
Aborted
Вы смотрели на код сборки, сгенерированный gcc, если бы ваш блок try {} содержал просто вызов функции? Я почти уверен, что компилятор C++ делает больше, чем просто переход в этот момент, поскольку ему нужно иметь возможность отследить стек при возникновении исключения.
Ваш код может быть работоспособным, если вы сможете имитировать шаги, которые gcc предпринимает при структурировании вызова функции.
Обновление: этот вопрос может дать больше информации. В частности, может оказаться полезной часть Itanium ABI, касающаяся бросания и перехвата: link
Вы смотрели, как ваша реализация обрабатывает исключения? Он включает в себя поиск адресов компьютеров в таблицах, чтобы выяснить, что программа делала в конкретном месте, которое бросило, и что делали все вызывающие абоненты. По крайней мере, в Mac OS X GCC.
Единственная другая система, на которую я смотрел, Metrowerks Codewarrior для Mac (когда-то давно) использовала аналогичную систему, хотя и несколько более прозрачную. Компилятор может прозрачно вставлять функции для любого изменения контекста исключения.
Вы не молитесь о том, чтобы сделать это портативным.
После выполнения встроенной сборки вы получаете поведение, определяемое реализацией (7.4 / 1).
Вам следует попробовать настроить стековый фрейм; детали зависят от платформы, и я не знаю, как это сделать на x86_64.