Cả node console và Qt5 của V8 dựa trên QJSEngine
có thể bị rơi bởi đoạn mã sau: sản lượngLàm thế nào để xử lý vụ tai nạn cơ V8 khi quá trình chạy ra khỏi bộ nhớ
a = []; for (;;) { a.push("hello"); }
nút trước khi vụ tai nạn:
FATAL ERROR: JS Allocation failed - process out of memory
Đầu ra của QJSEngine
trước khi tai nạn:
#
# Fatal error in JS
# Allocation failed - process out of memory
#
Nếu Tôi chạy ứng dụng thử nghiệm QJSEngine
của mình (xem bên dưới) dưới trình gỡ lỗi, nó hiển thị cuộc gọi v8::internal::OS::DebugBreak
bên trong mã V8. Nếu tôi quấn mã gọi QJSEngine::evaluate
vào __try-__except
(SEH), thì ứng dụng sẽ không gặp sự cố, nhưng giải pháp này dành riêng cho Windows.
Câu hỏi: Có cách nào để xử lý v8::internal::OS::DebugBreak
theo cách không phụ thuộc vào nền tảng trong các ứng dụng nút và Qt không?
=== mã kiểm tra QJSEngine ===
môi trường phát triển: QtCreator với Qt5 và Windows SDK 7.1, trên Windows XP SP3
QJSEngineTest.pro:
TEMPLATE = app
QT -= gui
QT += core qml
CONFIG -= app_bundle
CONFIG += console
SOURCES += main.cpp
TARGET = QJSEngineTest
chính .cpp không có SEH (điều này sẽ bị lỗi):
#include <QtQml/QJSEngine>
int main(int, char**)
{
try {
QJSEngine engine;
QJSValue value = engine.evaluate("a = []; for (;;) { a.push('hello'); }");
qDebug(value.isError() ? "Error" : value.toString().toStdString().c_str());
} catch (...) {
qDebug("Exception");
}
return 0;
}
main.cpp với SEH (điều này sẽ không sụp đổ, kết quả đầu ra "ngoại lệ Fatal"):
#include <QtQml/QJSEngine>
#include <Windows.h>
void runTest()
{
try {
QJSEngine engine;
QJSValue value = engine.evaluate("a = []; for (;;) { a.push('hello'); }");
qDebug(value.isError() ? "Error" : value.toString().toStdString().c_str());
} catch (...) {
qDebug("Exception");
}
}
int main(int, char**)
{
__try {
runTest();
} __except(EXCEPTION_EXECUTE_HANDLER) {
qDebug("Fatal exception");
}
return 0;
}
Cũng lưu ý rằng bạn có thể đăng ký gọi lại ngay trước khi hủy sử dụng V8 :: SetFatalErrorHandler(), mặc dù điều này vẫn không cung cấp cho bạn khả năng thư giãn ngăn xếp v8. Bạn cũng có thể kiểm soát OS :: Abort() bằng --no-hard_abort để làm cho quá trình thoát ra lặng lẽ (SIGABRT) thay vì vi phạm quyền truy cập (V8_IMMEDIATE_CRASH()). (Tôi không chắc chắn trong trường hợp nào DebugBreak() được gọi - chỉ có thể là khi một trình sửa lỗi được đính kèm.) –