Bug 27976

Summary: When the last heap in the user process into the non-main area has memory in use, even if the previous heap is already free, the previous heap will not be released
Product: glibc Reporter: liudongyun <liu.dongyun>
Component: mallocAssignee: Not yet assigned to anyone <unassigned>
Status: UNCONFIRMED ---    
Severity: normal    
Priority: P2    
Version: 2.33   
Target Milestone: ---   
Host: Target:
Build: Last reconfirmed:
Attachments: my idea

Description liudongyun 2021-06-10 10:03:21 UTC
bug:The system has a total of 32G memory. When the last heap in the user process into the non-main area has memory in use, even if the previous heap is already free, the previous heap will not be released, resulting in the memory cache reaching 20G.


for example:
I create a new thread and malloc(2000Bytes), the thread will attached to non-main-arena.I trim the heap->size = 512*1024 befor test ,then run the follow code. we can see the pLast not free,then the non-main-arena memory not free .This may cause the memory cached in the non-main-area to be unusable after the memory usage reaches its peak, and even most of the memory of the entire system can be cached.When the last pLast of memory is released, most of the memory in the entire non-main-area will be released to the system.

I tried to solve this problem by checking to release the heap that the current chunk belongs to and unmmaped if it is all free.The method has achieved good results.
---------------------------------------------------
void *pLast = NULL;
void  *free_last()
{
	free(pLast);
	return NULL;
}
void func1()
{
	void *pp[10240];
	int i = 0;
	
	for(i=0;i<10230;i++){
		 
		pp[i] = malloc(2048);
		memset(pp[i], 0, 2048);
	}
	
	pLast = malloc(2048);
	printf("pLast == %p     \n",pLast);
	memset(pLast, 0, 2048);
	
	for(i=0;i<10230;i++)
      free(pp[i]);
  
     printf("finish  malloc free \n");
	
}

int main()
{
	int i = 0;
	void *p = NULL;
	pthread_t  tid;
	p = malloc(1024);
	memset(p, 0, 1024);
	pthread_create(&tid, NULL, func1, NULL);

	while(1)
	{
		i++;
		sleep(10);
	}

	free_last();

}
---------------------------------------------------
Comment 1 liudongyun 2021-06-10 10:45:43 UTC
Created attachment 13490 [details]
my idea

When the user calls the free function, check whether the heap where the current chunk is located is free, and if so, release the entire heap