*fixed a crash bug when unreferencing a garbage; *fixed a multiple disposing bug when an error occurs in an expression.

This commit is contained in:
paladin-t 2016-03-02 13:36:03 +08:00
parent 9b0d8dc7fb
commit 426bf04b81
4 changed files with 53 additions and 28 deletions

View File

@ -1,3 +1,7 @@
Mar. 2 2016
Fixed a crash bug when unreferencing a garbage
Fixed a multiple disposing bug when an error occurs in an expression
Mar. 1 2016 Mar. 1 2016
Added an OS statement Added an OS statement
Fixed a variable pathing bug in lambda Fixed a variable pathing bug in lambda

View File

@ -1466,7 +1466,7 @@ static void _create_ref(_ref_t* ref, _unref_func_t dtor, _data_e t, mb_interpret
static void _destroy_ref(_ref_t* ref); static void _destroy_ref(_ref_t* ref);
static void _gc_add(_ref_t* ref, void* data, _gc_t* gc); static void _gc_add(_ref_t* ref, void* data, _gc_t* gc);
static void _gc_remove(_ref_t* ref, void* data); static void _gc_remove(_ref_t* ref, void* data, _gc_t* gc);
static int _gc_add_reachable(void* data, void* extra, void* h); static int _gc_add_reachable(void* data, void* extra, void* h);
static void _gc_get_reachable(mb_interpreter_t* s, _ht_node_t* ht); static void _gc_get_reachable(mb_interpreter_t* s, _ht_node_t* ht);
static int _gc_destroy_garbage_in_list(void* data, void* extra, _gc_t* gc); static int _gc_destroy_garbage_in_list(void* data, void* extra, _gc_t* gc);
@ -1632,6 +1632,7 @@ static int _internal_object_to_public_value(_object_t* itn, mb_value_t* pbl);
static int _create_internal_object_from_public_value(mb_value_t* pbl, _object_t** itn); static int _create_internal_object_from_public_value(mb_value_t* pbl, _object_t** itn);
static int _compare_public_value_and_internal_object(mb_value_t* pbl, _object_t* itn); static int _compare_public_value_and_internal_object(mb_value_t* pbl, _object_t* itn);
static void _try_clear_intermediate_value(void* data, void* extra, mb_interpreter_t* s); static void _try_clear_intermediate_value(void* data, void* extra, mb_interpreter_t* s);
static void _remove_if_exist(void* data, void* extra, _ls_node_t* ls);
static void _destroy_lazy_objects(mb_interpreter_t* s); static void _destroy_lazy_objects(mb_interpreter_t* s);
static void _mark_lazy_destroy_string(mb_interpreter_t* s, char* ch); static void _mark_lazy_destroy_string(mb_interpreter_t* s, char* ch);
static void _assign_public_value(mb_value_t* tgt, mb_value_t* src); static void _assign_public_value(mb_value_t* tgt, mb_value_t* src);
@ -3278,7 +3279,7 @@ _array:
ast = ast->prev; ast = ast->prev;
result = _get_array_index(s, &ast, c, &arr_idx, 0); result = _get_array_index(s, &ast, c, &arr_idx, 0);
if(result != MB_FUNC_OK) { if(result != MB_FUNC_OK) {
_handle_error_on_obj(s, SE_RN_CALCULATION_ERROR, s->source_file, DON(ast), MB_FUNC_ERR, _exit, result); _handle_error_on_obj(s, SE_RN_CALCULATION_ERROR, s->source_file, DON(ast), MB_FUNC_ERR, _error, result);
} }
ast = ast->next; ast = ast->next;
_get_array_elem(s, c->data.array, arr_idx, &arr_val, &arr_type); _get_array_elem(s, c->data.array, arr_idx, &arr_val, &arr_type);
@ -3288,7 +3289,7 @@ _array:
arr_elem->ref = true; arr_elem->ref = true;
_copy_bytes(arr_elem->data.bytes, arr_val.bytes); _copy_bytes(arr_elem->data.bytes, arr_val.bytes);
if(f) { if(f) {
_handle_error_on_obj(s, SE_RN_OPERATOR_EXPECTED, s->source_file, DON(ast), MB_FUNC_ERR, _exit, result); _handle_error_on_obj(s, SE_RN_OPERATOR_EXPECTED, s->source_file, DON(ast), MB_FUNC_ERR, _error, result);
} }
_ls_pushback(opnd, arr_elem); _ls_pushback(opnd, arr_elem);
f++; f++;
@ -3310,7 +3311,7 @@ _array:
running->calc_depth = calc_depth; running->calc_depth = calc_depth;
} }
if(result != MB_FUNC_OK) { if(result != MB_FUNC_OK) {
_handle_error_on_obj(s, SE_RN_CALCULATION_ERROR, s->source_file, DON(ast), MB_FUNC_ERR, _exit, result); _handle_error_on_obj(s, SE_RN_CALCULATION_ERROR, s->source_file, DON(ast), MB_FUNC_ERR, _error, result);
} }
c = _create_object(); c = _create_object();
_ls_pushback(garbage, c); _ls_pushback(garbage, c);
@ -3318,15 +3319,15 @@ _array:
if(c->type == _DT_STRING) if(c->type == _DT_STRING)
c->ref = true; c->ref = true;
if(result != MB_FUNC_OK) if(result != MB_FUNC_OK)
goto _exit; goto _error;
if(f) { if(f) {
_handle_error_on_obj(s, SE_RN_OPERATOR_EXPECTED, s->source_file, DON(ast), MB_FUNC_ERR, _exit, result); _handle_error_on_obj(s, SE_RN_OPERATOR_EXPECTED, s->source_file, DON(ast), MB_FUNC_ERR, _error, result);
} }
if(_is_array(c)) { if(_is_array(c)) {
goto _array; goto _array;
} else { } else {
if(ast && _IS_FUNC(ast->data, _core_open_bracket)) { if(ast && _IS_FUNC(ast->data, _core_open_bracket)) {
_handle_error_on_obj(s, SE_RN_SYNTAX, s->source_file, DON(ast), MB_FUNC_ERR, _exit, result); _handle_error_on_obj(s, SE_RN_SYNTAX, s->source_file, DON(ast), MB_FUNC_ERR, _error, result);
} }
} }
_ls_pushback(opnd, c); _ls_pushback(opnd, c);
@ -3364,15 +3365,15 @@ _routine:
if(ast) if(ast)
ast = ast->prev; ast = ast->prev;
if(result != MB_FUNC_OK) { if(result != MB_FUNC_OK) {
_handle_error_on_obj(s, SE_RN_CALCULATION_ERROR, s->source_file, DON(ast), MB_FUNC_ERR, _exit, result); _handle_error_on_obj(s, SE_RN_CALCULATION_ERROR, s->source_file, DON(ast), MB_FUNC_ERR, _error, result);
} }
c = _create_object(); c = _create_object();
_ls_pushback(garbage, c); _ls_pushback(garbage, c);
result = _public_value_to_internal_object(&running->intermediate_value, c); result = _public_value_to_internal_object(&running->intermediate_value, c);
if(result != MB_FUNC_OK) if(result != MB_FUNC_OK)
goto _exit; goto _error;
if(f) { if(f) {
_handle_error_on_obj(s, SE_RN_OPERATOR_EXPECTED, s->source_file, DON(ast), MB_FUNC_ERR, _exit, result); _handle_error_on_obj(s, SE_RN_OPERATOR_EXPECTED, s->source_file, DON(ast), MB_FUNC_ERR, _error, result);
} }
_ls_pushback(opnd, c); _ls_pushback(opnd, c);
f++; f++;
@ -3390,7 +3391,7 @@ _routine:
ast = ast->prev; ast = ast->prev;
result = _get_array_index(s, &ast, 0, &arr_idx, 0); result = _get_array_index(s, &ast, 0, &arr_idx, 0);
if(result != MB_FUNC_OK) { if(result != MB_FUNC_OK) {
_handle_error_on_obj(s, SE_RN_CALCULATION_ERROR, s->source_file, DON(ast), MB_FUNC_ERR, _exit, result); _handle_error_on_obj(s, SE_RN_CALCULATION_ERROR, s->source_file, DON(ast), MB_FUNC_ERR, _error, result);
} }
ast = ast->next; ast = ast->next;
_get_array_elem(s, c->data.variable->data->data.array, arr_idx, &arr_val, &arr_type); _get_array_elem(s, c->data.variable->data->data.array, arr_idx, &arr_val, &arr_type);
@ -3410,7 +3411,7 @@ _routine:
mb_assert(0 && "Unsupported."); mb_assert(0 && "Unsupported.");
} }
if(f) { if(f) {
_handle_error_on_obj(s, SE_RN_OPERATOR_EXPECTED, s->source_file, DON(ast), MB_FUNC_ERR, _exit, result); _handle_error_on_obj(s, SE_RN_OPERATOR_EXPECTED, s->source_file, DON(ast), MB_FUNC_ERR, _error, result);
} }
_ls_pushback(opnd, arr_elem); _ls_pushback(opnd, arr_elem);
f++; f++;
@ -3457,7 +3458,7 @@ _var:
case _DT_LIST: case _DT_LIST:
mb_check(mb_pop_int(s, (void**)l, &idx)); mb_check(mb_pop_int(s, (void**)l, &idx));
if(!_at_list(ocoll->data.list, idx, &ret)) { if(!_at_list(ocoll->data.list, idx, &ret)) {
_handle_error_on_obj(s, SE_RN_CANNOT_FIND_WITH_GIVEN_INDEX, s->source_file, TON(l), MB_FUNC_ERR, _exit, result); _handle_error_on_obj(s, SE_RN_CANNOT_FIND_WITH_GIVEN_INDEX, s->source_file, TON(l), MB_FUNC_ERR, _error, result);
} }
break; break;
@ -3465,7 +3466,7 @@ _var:
mb_make_nil(key); mb_make_nil(key);
mb_check(mb_pop_value(s, (void**)l, &key)); mb_check(mb_pop_value(s, (void**)l, &key));
if(!_find_dict(ocoll->data.dict, &key, &ret)) { if(!_find_dict(ocoll->data.dict, &key, &ret)) {
_handle_error_on_obj(s, SE_RN_CANNOT_FIND_WITH_GIVEN_INDEX, s->source_file, TON(l), MB_FUNC_ERR, _exit, result); _handle_error_on_obj(s, SE_RN_CANNOT_FIND_WITH_GIVEN_INDEX, s->source_file, TON(l), MB_FUNC_ERR, _error, result);
} }
break; break;
@ -3486,13 +3487,13 @@ _var:
} }
#endif /* MB_ENABLE_COLLECTION_LIB */ #endif /* MB_ENABLE_COLLECTION_LIB */
if(_IS_FUNC(_err_or_bracket, _core_open_bracket)) { if(_IS_FUNC(_err_or_bracket, _core_open_bracket)) {
_handle_error_on_obj(s, SE_RN_INVALID_ID_USAGE, s->source_file, DON(ast), MB_FUNC_ERR, _exit, result); _handle_error_on_obj(s, SE_RN_INVALID_ID_USAGE, s->source_file, DON(ast), MB_FUNC_ERR, _error, result);
} }
} while(0); } while(0);
} }
} }
if(f) { if(f) {
_handle_error_on_obj(s, SE_RN_OPERATOR_EXPECTED, s->source_file, DON(ast), MB_FUNC_ERR, _exit, result); _handle_error_on_obj(s, SE_RN_OPERATOR_EXPECTED, s->source_file, DON(ast), MB_FUNC_ERR, _error, result);
} }
_ls_pushback(opnd, c); _ls_pushback(opnd, c);
f++; f++;
@ -3504,7 +3505,7 @@ _var:
if(c->type == _DT_FUNC && !_is_operator(c->data.func->pointer) && !_is_flow(c->data.func->pointer)) { if(c->type == _DT_FUNC && !_is_operator(c->data.func->pointer) && !_is_flow(c->data.func->pointer)) {
_ls_foreach(opnd, _remove_source_object); _ls_foreach(opnd, _remove_source_object);
_handle_error_on_obj(s, SE_RN_COLON_EXPECTED, s->source_file, DON(ast), MB_FUNC_ERR, _exit, result); _handle_error_on_obj(s, SE_RN_COLON_EXPECTED, s->source_file, DON(ast), MB_FUNC_ERR, _error, result);
} }
ast = ast->next; ast = ast->next;
} else { } else {
@ -3534,7 +3535,7 @@ _var:
r = _operate_operand(s, theta, a, b, &result); r = _operate_operand(s, theta, a, b, &result);
if(!r) { if(!r) {
_ls_clear(optr); _ls_clear(optr);
_handle_error_on_obj(s, SE_RN_OPERATION_FAILED, s->source_file, DON(errn), MB_FUNC_ERR, _exit, result); _handle_error_on_obj(s, SE_RN_OPERATION_FAILED, s->source_file, DON(errn), MB_FUNC_ERR, _error, result);
} }
_ls_pushback(opnd, r); _ls_pushback(opnd, r);
_ls_pushback(garbage, r); _ls_pushback(garbage, r);
@ -3547,7 +3548,7 @@ _var:
} }
if(errn) { if(errn) {
_handle_error_on_obj(s, SE_RN_CLOSE_BRACKET_EXPECTED, s->source_file, DON(errn), MB_FUNC_ERR, _exit, result); _handle_error_on_obj(s, SE_RN_CLOSE_BRACKET_EXPECTED, s->source_file, DON(errn), MB_FUNC_ERR, _error, result);
} }
c = (_object_t*)(_ls_popback(opnd)); c = (_object_t*)(_ls_popback(opnd));
@ -3569,7 +3570,7 @@ _var:
_set_current_error(s, SE_RN_INVALID_DATA_TYPE, 0); _set_current_error(s, SE_RN_INVALID_DATA_TYPE, 0);
result = MB_FUNC_ERR; result = MB_FUNC_ERR;
goto _exit; goto _error;
} }
if(c->type == _DT_VAR) { if(c->type == _DT_VAR) {
(*val)->type = c->data.variable->data->type; (*val)->type = c->data.variable->data->type;
@ -3611,6 +3612,10 @@ _var:
} }
} }
while(0) {
_error:
_LS_FOREACH(garbage, _do_nothing_on_object, _remove_if_exist, opnd);
}
_exit: _exit:
_LS_FOREACH(garbage, _destroy_object, _try_clear_intermediate_value, s); _LS_FOREACH(garbage, _destroy_object, _try_clear_intermediate_value, s);
_ls_destroy(garbage); _ls_destroy(garbage);
@ -5329,15 +5334,17 @@ static _ref_count_t _ref(_ref_t* ref, void* data) {
static bool_t _unref(_ref_t* ref, void* data) { static bool_t _unref(_ref_t* ref, void* data) {
/* Decrease the reference of a stub by 1 */ /* Decrease the reference of a stub by 1 */
bool_t result = true; bool_t result = true;
_gc_t* gc = 0;
gc = &ref->s->gc;
result = --(*ref->count) == _NONE_REF; result = --(*ref->count) == _NONE_REF;
mb_assert(*ref->count >= _NONE_REF); mb_assert(*ref->count >= _NONE_REF);
_gc_add(ref, data, &ref->s->gc); _gc_add(ref, data, &ref->s->gc);
if(ref->count && *ref->count == _NONE_REF) if(ref->count && *ref->count == _NONE_REF)
_tidy_intermediate_value(ref, data); _tidy_intermediate_value(ref, data);
ref->on_unref(ref, data); ref->on_unref(ref, data);
if(!ref->count) if(result)
_gc_remove(ref, data); _gc_remove(ref, data, gc);
return result; return result;
} }
@ -5425,16 +5432,16 @@ static void _gc_add(_ref_t* ref, void* data, _gc_t* gc) {
_ht_remove(table, ref, 0); _ht_remove(table, ref, 0);
} }
static void _gc_remove(_ref_t* ref, void* data) { static void _gc_remove(_ref_t* ref, void* data, _gc_t* gc) {
/* Remove a referenced object from GC */ /* Remove a referenced object from GC */
_ht_node_t* table = 0; _ht_node_t* table = 0;
mb_assert(ref && data); mb_assert(ref && data && gc);
if(ref->s->gc.collecting) if(gc->collecting)
table = ref->s->gc.recursive_table; table = gc->recursive_table;
else else
table = ref->s->gc.table; table = gc->table;
if(table) if(table)
_ht_remove(table, ref, 0); _ht_remove(table, ref, 0);
@ -8896,6 +8903,15 @@ static void _try_clear_intermediate_value(void* data, void* extra, mb_interprete
} }
} }
static void _remove_if_exist(void* data, void* extra, _ls_node_t* ls) {
/* Remove from another list if exist */
_object_t* obj = 0;
mb_unrefvar(extra);
obj = (_object_t*)data;
_ls_try_remove(ls, obj, _ls_cmp_data, 0);
}
static void _destroy_lazy_objects(mb_interpreter_t* s) { static void _destroy_lazy_objects(mb_interpreter_t* s) {
/* Destroy lazy releasing objects */ /* Destroy lazy releasing objects */
_ls_foreach(s->lazy_destroy_objects, _destroy_object); _ls_foreach(s->lazy_destroy_objects, _destroy_object);
@ -12918,7 +12934,8 @@ _elseif:
_exit: _exit:
if(result == MB_SUB_RETURN) { if(result == MB_SUB_RETURN) {
ast = ast->prev; if(ast)
ast = ast->prev;
} else { } else {
if(multi_line) { if(multi_line) {
int ret = MB_FUNC_OK; int ret = MB_FUNC_OK;

Binary file not shown.

View File

@ -86,6 +86,7 @@ extern "C" {
/* Define as 1 to use memory pool, 0 to disable */ /* Define as 1 to use memory pool, 0 to disable */
#define _USE_MEM_POOL 1 #define _USE_MEM_POOL 1
#define _RESET_WHEN_PUSH_TO_POOL 1
#define _MAX_LINE_LENGTH 256 #define _MAX_LINE_LENGTH 256
#define _str_eq(__str1, __str2) (mb_stricmp((__str1), (__str2)) == 0) #define _str_eq(__str1, __str2) (mb_stricmp((__str1), (__str2)) == 0)
@ -357,6 +358,9 @@ static void _push_mem(char* p) {
} }
alloc_bytes -= _POOL_NODE_SIZE(p); alloc_bytes -= _POOL_NODE_SIZE(p);
#if _RESET_WHEN_PUSH_TO_POOL
memset(p, 0, _POOL_NODE_SIZE(p));
#endif /* _RESET_WHEN_PUSH_TO_POOL */
if(pool_count) { if(pool_count) {
for(i = 0; i < pool_count; i++) { for(i = 0; i < pool_count; i++) {
pl = &pool[i]; pl = &pool[i];