Closed weixiongmei closed 2 years ago
It would be good to know what the function that you're calling does.
jerry_call
returns with the value returned by the function, it's possible that needs to be freed as well.
Based on the error message, the most likely cause is that the Array object is leaking at some point, however based on the above code alone it's not possible to tell where exactly.
Hi, it's just an empty javascript function, and has not return. Here's the code.
let test_func = function(arg0, arg1) { };
Hi,
I've created a simple example application based on the details you provided (with minor modifications), see:
#include "jerryscript.h"
int main (void)
{
jerry_init (JERRY_INIT_EMPTY);
const jerry_char_t script[] = "function test_func(arg0, arg1) { };";
jerry_value_t parsed_code = jerry_parse(script, sizeof (script) - 1, NULL);
if (!jerry_value_is_error(parsed_code))
{
jerry_value_t ret_value = jerry_run(parsed_code);
jerry_value_free(ret_value);
}
jerry_value_free(parsed_code);
// Get the test function
jerry_value_t global = jerry_current_realm();
jerry_value_t jerry_function_demo = jerry_object_get_sz (global, "test_func");
jerry_value_free (global);
for (int i = 0; i < 1000000; i++) {
jerry_value_t jerry_arguments[2];
jerry_arguments[0] = jerry_number(12321211414.3);
jerry_arguments[1] = jerry_array(1);
jerry_value_t element_0 = jerry_number(3.1231231212);
jerry_value_free( jerry_object_set_index(jerry_arguments[1], 0, element_0) );
jerry_value_free(element_0); // This is required
jerry_value_t result = jerry_call(jerry_function_demo, jerry_undefined(), jerry_arguments, 2);
jerry_value_free(result); // result must be freed
jerry_value_free(jerry_arguments[0]);
jerry_value_free(jerry_arguments[1]);
}
jerry_value_free(jerry_function_demo);
jerry_cleanup();
return 0;
}
Using this, I was unable to reproduce the ref count limit error. Still a few important key points:
jerry_call
's result must be freedjerry_number
must be also freed (there are some cases where this could be skipped if the number is a very small number, but that is an internal thing and can change, so don't build on skipping free)How do you load thetest_func
js function's value into a jerry_value_t
? (which API calls are you using?)
Hi @galpeter, thank you very much, seems like my problem is half way solved, i didn't freed the returned value of jerry_call, and didn't freed all the items of an array, but still having problem if the array contains jerry_string like the code below, would you mind to test it with a jerry_string item in the array? Thanks
char* test_string = "jerry test string";
jerry_value_t element_1 = jerry_string((jerry_char_t*)test_string, strlen(test_string), JERRY_ENCODING_UTF8);
jerry_value_free( jerry_object_set_index(jerry_arguments[1], 1, element_1));
jerry_value_free(element_1);
I've added the code part you mentioned to the example above (just before the jerry_call) and it works without any errors. I think there the problem lies somewhere else.
@galpeter I think I found the issue, would you mind to try one more thing please? Thank you~
class Item {
constructor(d0 = 0, l0 = false, d1 = 0, l1 = false) {
this.da0 = d0;
this.le0 = l0;
this.da1 = d1;
this.le1 = l1;
Object.seal(this);
}
}
let items = new Array(24);
for (let i = 0; i < 24; i++) {
items[i] = new Item();
}
while(true)
{
native_c_function(items.map(item => Object.values(item)))
}
static jerry_value_t native_c_function(const jerry_call_info_t* call_info_p, const jerry_value_t arguments[], const jerry_length_t arguments_count)
{
return jerry_undefined();
}
@galpeter I think I found the issue, would you mind to try one more thing please? Thank you~
Just to make sure, I've tried out this one also. There were no errors (excluding the fact that the while(true)
never exited). The code I've used is:
#include "jerryscript.h"
#include <string.h>
#define XSTR(s) #s
#define STR(s) XSTR(s)
static jerry_value_t
demo_handler (const jerry_call_info_t *call_info_p, const jerry_value_t args_p[], const jerry_length_t args_cnt) {
(void) call_info_p;
(void) args_p;
(void) args_cnt;
return jerry_undefined();
}
int main (void) {
const jerry_char_t script[] = STR(
class Item {
constructor(d0 = 0, l0 = false, d1 = 0, l1 = false) {
this.da0 = d0;
this.le0 = l0;
this.da1 = d1;
this.le1 = l1;
Object.seal(this);
}
}
let items = new Array(24);
for (let i = 0; i < 24; i++) {
items[i] = new Item();
};
while(true)
{
native_c_function(items.map(item => Object.values(item)));
}
);
jerry_init (JERRY_INIT_EMPTY);
jerry_value_t global = jerry_current_realm ();
jerry_value_t func_handler = jerry_function_external (demo_handler);
jerry_value_free (jerry_object_set_sz (global, "native_c_function", func_handler));
jerry_value_free (func_handler);
jerry_value_free (global);
jerry_value_t parsed_code = jerry_parse (script, sizeof (script) - 1, NULL);
if (!jerry_value_is_error (parsed_code))
{
jerry_value_t ret_value = jerry_run (parsed_code); // This will never return
jerry_value_free (ret_value);
}
jerry_value_free (parsed_code);
jerry_cleanup ();
return 0;
}
JerryScript revision
d00f4810b0e8eaa6a6755e2d0ecbd1713ecfca49
Test case
Error Code
Good Code
Execution steps
Call the above code in the Error Section every 1 second, it will randomly causing JERRY_FATAL_REF_COUNT_LIMIT within an hour.