KEIL MDK使用malloc申请堆空间注意事项

项目场景:

最近有个案子(MCU:STM32F103VCT6)需要定制个小功能,需要用malloc分配大量的空间。本来是没什么,但是无意中发现,KEIL MDK编译时,malloc分配的空间已经超过预设的大小也不报错。后面发现和自己的使用也有关系。在这边记录一下,给有碰到类似问题的网友们一些参考。


问题描述:

先看启动文件。这里堆分配的大小是0x2000,即8K。

Heap_Size       EQU     0x00002000
                AREA    HEAP, NOINIT, READWRITE, ALIGN=3
__heap_base
Heap_Mem        SPACE   Heap_Size
__heap_limit

在代码里,我创建了一个uint16的数组,数量是4500。所以大小是9000,已经溢出了。

U8 TagGet(void)
{
	U8 statue=FALSE;
	U16 *pbuf;
	U16 cnt,i,j;
	U16 const len = 4500;
	
	pbuf = (U16 *)malloc(sizeof(U16)*len);
	printf("pbuf = 0x%x\r\n",*pbuf);
	
	if(*pbuf == NULL) 
		statue=FALSE;
	
	printf("sizeof malloc = %d\r\n",sizeof(U16)*len);
	printf("sizeof malloc = 0x%X\r\n\r\n",sizeof(U16)*len);

	/* 数组赋值。从0~4500依次按顺序赋值 */
	for(i = 0;i<len;i++)
	{
		pbuf[i] = i;
	}

	/* 输出数组查看 */
	for(i = 0,j = 0;i<len;i=i+5)
	{
		printf("i = %6d,value = %6d ; ",i,pbuf[i]);
		
		if((j+1)%2==0)
			printf("\r\n");
		j++;
	}
	printf("\r\n");


	free(pbuf);
	pbuf = NULL;
	statue=TRUE;
	return statue;	
}

原以为KEIL MDK会报错,但是实际没有报错。
由于程序里有给数组赋值。从0~4500依次按顺序赋值。根据串口信息发现数组异常,读出的参数全是乱的。
KEIL MDK使用malloc申请堆空间注意事项

KEIL MDK使用malloc申请堆空间注意事项
后面才意识到是分配的空间超标了。
所以把分配的数量减小到2000,总数也才4000,在堆的最大限度以内。
编译后,载入再看信息,一切正常。分配的空间可以正常访问。

KEIL MDK使用malloc申请堆空间注意事项


原因:

由此可见KEIL MDK并不会对malloc分配的空间进行合理的判断,并给出报错。
就算malloc的空间已经超出启动文件里限制的大小,也不会报错。
所以MDK编译阶段,只判断malloc语法的对错,不能分辨堆的申请是否超过预先设定的最大值。资源的分配成功与否,需要我们在代码的逻辑层再做判断。申请失败,则独立处理。

我也发现我的代码处理的也有问题。KEIL MDK虽然在编译阶段不报错,但是在实际运行到malloc时,已经发现空间不足,并给出提示,是我程序对返回值的操作不当,资源分配异常时没有及时处理。

原来的SRC:

if(*pbuf == NULL) 
		statue=FALSE;

应该改成:

if(pbuf == NULL) {
		statue=FALSE;
		
		return statue;
	}

地址分配失败直接退出。(这边处理比较简单,实际看个人需求)

小结:

对于malloc,MDK编译阶段,只判断malloc语法的对错,不能分辨堆的申请是否超过预先设定的最大值。虽然在编译阶段不报错,但是在实际运行到malloc时,已经发现空间不足,发现空间不足会返回一个空值,我们自己要在代码里做判断。

(tip:malloc分配成功,会返回分配空间的起始地址;分配失败,返回0。)
所以判断方式都类似,可以直接套用以下处理方式:

	pbuf = (U16 *)malloc(sizeof(U16)*len);
	
	if(*pbuf == NULL) 
		return;
上一篇:STM32双轴摇杆控制空心杯电机


下一篇:51单片机学习