fixed serious memory management bugs

This commit is contained in:
Valk Richard Li 2020-04-04 19:03:09 +08:00 committed by GitHub
parent 60c94ad5e6
commit 8477a5662f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 141 additions and 28 deletions

View File

@ -116,22 +116,109 @@ struct gc_unit
return;
}
};
#ifndef NAS_POOL_SIZE
#define NAS_POOL_SIZE 128
struct memory_block
{
gc_unit space[NAS_POOL_SIZE];
memory_block* next;
};
class memory_block_list
{
private:
memory_block* head;
int mem_size;
int blk_size;
public:
memory_block_list()
{
mem_size=0;
blk_size=1;
head=new memory_block;
head->next=NULL;
return;
}
~memory_block_list()
{
mem_size=0;
blk_size=0;
memory_block* ptr=head;
while(ptr)
{
memory_block* tmp_ptr=ptr;
ptr=ptr->next;
delete tmp_ptr;
}
return;
}
void clear()
{
memory_block* ptr=head;
while(ptr)
{
memory_block* tmp_ptr=ptr;
ptr=ptr->next;
delete tmp_ptr;
}
mem_size=0;
blk_size=1;
head=new memory_block;
head->next=NULL;
return;
}
gc_unit& operator[](int address)
{
int block_num=address/NAS_POOL_SIZE;
int block_plc=address%NAS_POOL_SIZE;
memory_block* ptr=head;
for(int i=0;i<block_num;++i)
ptr=ptr->next;
return ptr->space[block_plc];
}
void push_back()
{
++mem_size;
if(mem_size>blk_size*NAS_POOL_SIZE)
{
memory_block* ptr=head;
while(ptr->next)
ptr=ptr->next;
ptr->next=new memory_block;
ptr->next->next=NULL;
++blk_size;
}
return;
}
int size()
{
return mem_size;
}
int capacity()
{
return NAS_POOL_SIZE*blk_size;
}
};
#endif
class gc_manager
{
private:
// free_space list is used to store space that is not in use.
std::list<int> free_space;
std::vector<gc_unit> memory;
/*
cannot use std::vector to simulate memory
because if vector memory is not enough,vector will use another larger memory as it's main memory
then all the things will be moved to a new space,
at this time if you reference a member in it,this will cause segmentation error.
*/
memory_block_list memory;
bool error_occurred;
public:
void gc_init()
{
// this function must be called in class nasal_runtime before running any codes
std::vector<gc_unit> tmp_vec;
memory.clear();
memory.swap(tmp_vec);
// clear the memory capacity by using tmp_vec.~vector<gc_unit>()
free_space.clear();
error_occurred=false;
return;
@ -144,8 +231,7 @@ class gc_manager
// by this way it can manage memory efficiently.
if(free_space.empty())
{
gc_unit new_unit;
memory.push_back(new_unit);
memory.push_back();
free_space.push_back(memory.size()-1);
}
int alloc_plc=free_space.front();
@ -171,7 +257,7 @@ class gc_manager
// this function is often used when an identifier is calling a space in memory
return (0<=addr) && (addr<memory.size()) && (!memory[addr].collected);
}
void reference_add(const int addr)
bool reference_add(const int addr)
{
if((0<=addr) && (addr<memory.size()) && (!memory[addr].collected))
++memory[addr].refcnt;
@ -180,11 +266,11 @@ class gc_manager
std::cout<<">> [Gc] fatal error: reference unexpected memory place ";
prt_hex(addr);
std::cout<<" ."<<std::endl;
error_occurred=true;
return false;
}
return;
return true;
}
void reference_delete(const int addr)
bool reference_delete(const int addr)
{
if((0<=addr) && (addr<memory.size()) && (!memory[addr].collected))
{
@ -212,9 +298,9 @@ class gc_manager
std::cout<<">> [Gc] fatal error: delete unexpected memory address: ";
prt_hex(addr);
std::cout<<" ."<<std::endl;
error_occurred=true;
return false;
}
return;
return true;
}
void info_print()
{

View File

@ -1,8 +1,9 @@
#ifndef __NASAL_RUNTIME_H__
#define __NASAL_RUNTIME_H__
#define nas_lib_func_num 31
#define nas_lib_func_num 32
std::string inline_func_name[nas_lib_func_num]=
{
"nasal_call_inline_scalar_type",
//base.nas
"nasal_call_inline_push_back",
"nasal_call_inline_push_null",
@ -3352,6 +3353,13 @@ int nasal_runtime::call_identifier(std::list<std::map<std::string,int> >& local_
for(std::list<std::map<std::string,int> >::iterator iter=local_scope.begin();iter!=local_scope.end();++iter)
if(iter->find(tmp_id_name)!=iter->end())
addr=(*iter)[tmp_id_name];
if(addr>0 && !nasal_gc.get_reference(addr))
{
std::cout<<">> [Runtime] line "<<node.get_node_line()<<": \'"<<tmp_id_name<<"\' has 0 reference ,address: ";
prt_hex(addr);
std::cout<<std::endl;
return -1;
}
if(addr<0)
{
/*
@ -3958,6 +3966,7 @@ int nasal_runtime::call_identifier(std::list<std::map<std::string,int> >& local_
last_hash_addr);
if(addr<0)
return -1;
nasal_gc.reference_delete(tmp_addr);
}
}
return addr;
@ -4122,19 +4131,20 @@ int nasal_runtime::loop_expr(std::list<std::map<std::string,int> >& local_scope,
std::map<std::string,int> new_scope;
local_scope.push_back(new_scope);
int loop_type=node.get_node_type();
int state=__state_no_operation;
if(loop_type==__while)
{
while(check_condition(local_scope,node.get_children().front()))
{
int state=block_proc(local_scope,node.get_children().back());
state=block_proc(local_scope,node.get_children().back());
if(state==__state_break)
break;
else if(state==__state_continue)
;
else if(state==__state_return)
return __state_return;
break;
else if(state==__state_error)
return __state_error;
break;
else if(state==__state_no_operation)
;
}
@ -4171,15 +4181,15 @@ int nasal_runtime::loop_expr(std::list<std::map<std::string,int> >& local_scope,
int tmp_val=assignment(local_scope,assignment_ast,now_step_elem_addr);
if(tmp_val>=0)
nasal_gc.reference_delete(tmp_val);
int state=block_proc(local_scope,*iter);
state=block_proc(local_scope,*iter);
if(state==__state_break)
break;
else if(state==__state_continue)
;
else if(state==__state_return)
return __state_return;
break;
else if(state==__state_error)
return __state_error;
break;
else if(state==__state_no_operation)
;
}
@ -4222,15 +4232,15 @@ int nasal_runtime::loop_expr(std::list<std::map<std::string,int> >& local_scope,
if(tmp_val>=0)
nasal_gc.reference_delete(tmp_val);
nasal_gc.reference_delete(tmp_addr);
int state=block_proc(local_scope,*iter);
state=block_proc(local_scope,*iter);
if(state==__state_break)
break;
else if(state==__state_continue)
;
else if(state==__state_return)
return __state_return;
break;
else if(state==__state_error)
return __state_error;
break;
else if(state==__state_no_operation)
;
}
@ -4250,16 +4260,15 @@ int nasal_runtime::loop_expr(std::list<std::map<std::string,int> >& local_scope,
// run block
while(check_condition(local_scope,*condition_iterator))
{
int state=block_proc(local_scope,*block_proc_iterator);
state=block_proc(local_scope,*block_proc_iterator);
if(state==__state_break)
break;
else if(state==__state_continue)
;
else if(state==__state_return)
return __state_return;
break;
else if(state==__state_error)
return __state_error;
break;
else if(state==__state_no_operation)
;
// step update here
@ -4267,7 +4276,10 @@ int nasal_runtime::loop_expr(std::list<std::map<std::string,int> >& local_scope,
{
int assign_addr=calculation(local_scope,*step_iterator);
if(assign_addr<0)
return __state_error;
{
state=__state_error;
break;
}
nasal_gc.reference_delete(assign_addr);
}
}
@ -4275,7 +4287,7 @@ int nasal_runtime::loop_expr(std::list<std::map<std::string,int> >& local_scope,
for(std::map<std::string,int>::iterator i=local_scope.back().begin();i!=local_scope.back().end();++i)
nasal_gc.reference_delete(i->second);
local_scope.pop_back();
return __state_no_operation;
return state;
}
int nasal_runtime::conditional(std::list<std::map<std::string,int> >& local_scope,abstract_syntax_tree& node)
{
@ -4412,7 +4424,10 @@ int nasal_runtime::func_proc(
// there may be an error if an identifier has the same name as one identifier in the local_scope before
if(called_hash_addr>=0)
{
new_scope["me"]=called_hash_addr;
nasal_gc.reference_add(called_hash_addr);
}
// loading parameters
std::vector<std::string> para_name_list;
int dynamic_args=-1;
@ -4668,6 +4683,18 @@ int nasal_runtime::inline_function(std::list<std::map<std::string,int> >& local_
case scalar_function:std::cout<<"func(...){...}";break;
}
}
ret_addr=nasal_gc.gc_alloc();
nasal_gc.get_scalar(ret_addr).set_type(scalar_nil);
}
else if(func_name=="nasal_call_inline_scalar_type")
{
int data=-1;
for(std::list<std::map<std::string,int> >::iterator i=local_scope.begin();i!=local_scope.end();++i)
if(i->find("thing")!=i->end())
data=(*i)["thing"];
if(data<0)
return -1;
print_scalar_type(nasal_gc.get_scalar(data).get_type());
std::cout<<std::endl;
ret_addr=nasal_gc.gc_alloc();
nasal_gc.get_scalar(ret_addr).set_type(scalar_nil);