this question에서 학습 한 후 힙에 SpiderMonkey의 전역 개체를 저장하려고합니다. 이것은 JS_DestroyRuntime
이 호출되기 전에 범위를 벗어나는 한 작동하는 것 같습니다. 그러나 내 코드에서 전역 개체는 클래스 멤버이므로 클래스의 소멸자에서 런타임이 삭제되기 전에 범위를 벗어날 수 없습니다. 여기JS :: Heap에 글로벌 js 개체를 저장하는 중
1 js::gc::Cell::storeBuffer() const Heap.h 1339 0x10004f905
2 JSObject::writeBarrierPost(void *, JSObject *, JSObject *) jsobj.h 655 0x1000a6fc8
3 js::InternalGCMethods<JSObject *>::postBarrier(JSObject * *, JSObject *, JSObject *) Barrier.h 254 0x1000a6df0
4 JS::HeapObjectPostBarrier(JSObject * *, JSObject *, JSObject *) Barrier.cpp 173 0x100bc1636
5 js::GCMethods<JSObject *>::postBarrier(JSObject * *, JSObject *, JSObject *) RootingAPI.h 551 0x100003065
6 JS::Heap<JSObject *>::post(JSObject * const&, JSObject * const&) RootingAPI.h 271 0x10000302b
7 JS::Heap<JSObject *>::~Heap() RootingAPI.h 237 0x10000369e
8 JS::Heap<JSObject *>::~Heap() RootingAPI.h 236 0x100002f75
9 MyMonkeyClass::~MyMonkeyClass() main.cpp 64 0x100003725
10 MyMonkeyClass::~MyMonkeyClass() main.cpp 58 0x100002aa5
11 main main.cpp 110 0x100002a12
12 start 0x1000029d4
을 문제를 유발 최소한의 예입니다
불행하게도,이 다음과 같은 스택 추적과 JS::~Heap
에서 충돌 원숭이로 연결됩니다. GC 추적을 의도적으로 호출하도록 남겨 두었으므로 결과를 변경하지 않습니다.
#include <js/Initialization.h>
#include <jsapi.h>
#include <QDebug>
// The class of the global object. Just a dummy.
static JSClass global_class = {
"global",
JSCLASS_GLOBAL_FLAGS,
nullptr,
nullptr,
nullptr,
nullptr,
nullptr,
nullptr,
nullptr,
nullptr,
nullptr,
nullptr,
nullptr,
JS_GlobalObjectTraceHook
};
class MyMonkeyClass
{
public:
MyMonkeyClass() {
Q_ASSERT(JS_Init());
auto runtime = JS_NewRuntime(5 * 1024 * 1024 /*heap space*/);
Q_ASSERT(runtime);
m_context = JS_NewContext(runtime, 8192 /*default. keep.*/);
Q_ASSERT(m_context);
JSAutoRequest ar(m_context);
// Not sure which of these alternatives is the correct way with JS::Heap
m_global = JS::RootedObject(m_context,
JS_NewGlobalObject(m_context, &global_class, nullptr, JS::FireOnNewGlobalHook));
//global = JS_NewGlobalObject(context, &global_class, nullptr, JS::FireOnNewGlobalHook);
Q_ASSERT(m_global.get());
}
~MyMonkeyClass() {
auto runtime = JS_GetRuntime(m_context);
JS_DestroyContext(m_context);
JS_DestroyRuntime(runtime);
JS_ShutDown();
}
private:
JSContext *m_context;
JS::Heap<JSObject*> m_global;
};
int main(int, char**)
{
MyMonkeyClass mmc;
return 0;
}
내가 일을 파괴하기 전에 dtor에서 m_global = nullptr;
을 설정하면 실제로 충돌을 피할 수 있다는 것을 발견이 질문을 작성하는 동안. 이제 내 마지막 질문 :
올바른 픽스입니까? 그렇다면 왜? SM은 비 null JS :: Heap 포인터가 여전히 사용중인 메모리를 참조하므로 패닉이 발생한다고 가정 할 수 있습니까?