Question
You need to specify the time to release the memory allocated for JSVM_CallbackStruct using new().
Possible Causes
The lifecycle of JSVM_CallbackStruct is not correctly managed. An example of the error code is as follows:
JSVM_Value CreateFunction(JSVM_Env env) {
JSVM_CallbackStruct callbackStruct;
callbackStruct.data = nullptr;
callbackStruct.callback = [](JSVM_Env env, JSVM_CallbackInfo info) -> JSVM_Value {
return nullptr;
};
JSVM_Value result = nullptr;
OH_JSVM_CreateFunction(env, "foo", JSVM_AUTO_LENGTH, &callbackStruct, &result);
return result;
}
void SomeFunction() {
char stack[] = "hello world";
} The application crashes when the following code is executed:
// ... auto func = CreateFunction(env); SomeFunction(); JSVM_Value undef = nullptr; OH_JSVM_GetUndefined(env, &undef); JSVM_Value result; OH_JSVM_CallFunction(env, undef, func, 0, nullptr, &result); // ...
When OH_JSVM_CallFunction is called, callbackStruct is a variable on the stack, and OH_JSVM_CreateFunction receives the stack memory address (&callbackStruct). After SomeFunction is called, the stack memory is modified. When OH_JSVM_CallFunction is called, the callback function in JSVM_CallbackStruct is executed. Because the memory of JSVM_CallbackStruct has been modified, invalid memory access causes the application to crash.
Answer
If the JavaScript function created using OH_JSVM_CreateFunction needs to be used across functions, the memory for JSVM_CallbackStruct must be applied for from the heap and cannot be released before the JavaScript function becomes invalid. The memory of JSVM_CallbackStruct can be released by the garbage collection mechanism of the VM. You can call OH_JSVM_AddFinalizer to set the Finalize method for the JavaScript function. When the JavaScript function is garbage collected, the Finalize method is called and JSVM_CallbackStruct is released. Refer to the code snippet below:
JSVM_Value CreateFunction(JSVM_Env env) {
JSVM_Callback cb = new JSVM_CallbackStruct;
cb->data = nullptr;
cb->callback = [](JSVM_Env env, JSVM_CallbackInfo info) -> JSVM_Value { return nullptr; };
JSVM_Value result = nullptr;
OH_JSVM_CreateFunction(env, "foo", JSVM_AUTO_LENGTH, cb, &result);
OH_JSVM_AddFinalizer(
env, result, reinterpret_cast<void *>(cb),
[](JSVM_Env env, void *data, void *hint) -> void {
delete static_cast<JSVM_Callback>(data);
}, nullptr, nullptr);
return result;
}