C setjmp-longjmp Unterstützung

Die setjmp-longjmp-Unterstützung ist in Emscripten standardmäßig aktiviert. Dies wird durch die Einstellung SUPPORT_LONGJMP gesteuert, die folgende Werte annehmen kann

  • emscripten: JavaScript-basierte Unterstützung

  • wasm: WebAssembly-Ausnahmebehandlungsbasierte Unterstützung

  • 0: Keine Unterstützung

  • 1: Standard-Unterstützung, abhängig vom Ausnahmemodus. wasm, wenn -fwasm-exception verwendet wird, emscripten sonst.

Wenn native Wasm-Ausnahmen verwendet werden, ist SUPPORT_LONGJMP standardmäßig auf wasm eingestellt, und wenn JavaScript-basierte Ausnahmen verwendet werden oder keine Ausnahmen unterstützt werden, ist es standardmäßig auf emscripten eingestellt.

setjmp speichert Informationen über die aufrufende Umgebung in einem Puffer, und longjmp überträgt die Kontrolle mithilfe des Puffers an den Punkt zurück, an dem setjmp aufgerufen wurde. Der Aufrufstapel von longjmp sollte die Funktion enthalten, von der setjmp aufgerufen wurde.

Die Unterstützung von Emscripten hat die Einschränkung, dass indirekte Aufrufe an setjmp nicht unterstützt werden. Zum Beispiel funktioniert das Folgende nicht

jmp_buf env;
int (*fp)(jmp_buf) = setjmp;
fp(env); // Doesn't work

JavaScript-basierte setjmp-longjmp Unterstützung

In diesem Modus emuliert Emscripten setjmp-longjmp mithilfe von JavaScript. Diese Option wird durch Hinzufügen von -sSUPPORT_LONGJMP=emscripten zur Befehlszeile festgelegt, ist aber derzeit standardmäßig aktiviert.

Beachten Sie, dass diese Option einen relativ hohen Overhead in Bezug auf die Code-Größe haben kann, aber auf allen JavaScript-Engines mit WebAssembly-Unterstützung funktioniert, selbst wenn diese den neuen Vorschlag zur WebAssembly-Ausnahmebehandlung noch nicht unterstützen.

WebAssembly Exception Handling-basierte setjmp-longjmp Unterstützung

Alternativ können Sie die neue Unterstützung mithilfe des Vorschlags zur WebAssembly-Ausnahmebehandlung aktivieren. Um diese zu aktivieren, übergeben Sie -sSUPPORT_LONGJMP=wasm sowohl zur Kompilierungszeit als auch zur Linkzeit.

Diese Option nutzt eine neue Funktion, die integrierte Anweisungen zum Auslösen und Abfangen von Ausnahmen in WebAssembly einführt. Dadurch kann sie die Code-Größe und den Leistungs-Overhead im Vergleich zur JavaScript-basierten Implementierung reduzieren. Diese Option wird derzeit in mehreren wichtigen Webbrowsern unterstützt, wird aber möglicherweise noch nicht in allen WebAssembly-Engines unterstützt.

Verwendung von Ausnahmen und setjmp-longjmp zusammen

Wir haben auch zwei Arten von Ausnahmebehandlungsunterstützung: JavaScript-basierte Unterstützung und die neue WebAssembly EH-basierte Unterstützung. Unsere setjmp-longjmp-Unterstützung verwendet die gleichen Mechanismen. Aus diesem Grund sollten Sie dieselbe Art von EH- und setjmp-longjmp-Unterstützung verwenden, wenn Sie Ausnahmen und setjmp-longjmp zusammen verwenden.

Um beispielsweise die JavaScript-basierte EH- und setjmp-longjmp-Unterstützung zusammen zu verwenden

em++ -fexceptions test.cpp -o test.js

-sSUPPORT_LONGJMP, das standardmäßig auf emscripten oder wasm eingestellt ist, je nach Ausnahmemodus, ist standardmäßig aktiviert, sodass Sie es nicht explizit übergeben müssen.

Um die WebAssembly EH- und setjmp-longjmp-Unterstützung zusammen zu verwenden

em++ -fwasm-exceptions -sSUPPORT_LONGJMP=wasm test.cpp -o test.js

Es gibt eine spezifische Einschränkung für die gleichzeitige Verwendung der WebAssembly EH-basierten Unterstützung für Ausnahmen und setjmp-longjmp. Sie können setjmp nicht innerhalb einer C++-catch-Klausel aufrufen. Zum Beispiel führt das Folgende zu einem Fehler während der Kompilierungszeit

try {
  ...
catch (int n) {
  setjmp(buf); // Doesn't work
}

Das Aufrufen von setjmp innerhalb einer try-Klausel ist in Ordnung. Das Aufrufen einer anderen Benutzerfunktion, die setjmp innerhalb einer catch-Klausel aufruft, ist ebenfalls in Ordnung.

try {
  setjmp(buf); // Works
catch (int n) {
  ...
}

try {
  ...
} catch (int n) {
  function_that_calls_setjmp(); // Works
}