FreeRTOS动态内存分配管理heap_4示例

目录
  • heap_4.c 内存堆管理
    • 数据结构如下
  • 分配
  • 内存堆初始化
  • 把新构造的结构体插入空闲链表
  • 释放
  • 还剩空闲字节数
  • 历史剩余最小字节数
  • 适用范围、特点

heap_4.c 内存堆管理

heap_4也是用链表来管理,但是链表头用的是结构体,链表尾用的是指针,链表尾占用ucHeap内存

数据结构如下

/* Define the linked list structure.  This is used to link free blocks in order
of their memory address. */
typedef struct A_BLOCK_LINK
{
	struct A_BLOCK_LINK *pxNextFreeBlock;	/*<< The next free block in the list. */
	size_t xBlockSize;						/*<< The size of the free block. */
} BlockLink_t;

头尾链表如下,注意pxEnd是指针

/* Create a couple of list links to mark the start and end of the list. */
static BlockLink_t xStart, *pxEnd = NULL;

分配

void *pvPortMalloc( size_t xWantedSize )
{
BlockLink_t *pxBlock, *pxPreviousBlock, *pxNewBlockLink;
void *pvReturn = NULL;
	//挂起调度器,防止函数重入
	vTaskSuspendAll();
	{
		/* If this is the first call to malloc then the heap will require
		initialisation to setup the list of free blocks. */
		//pxEnd是NULL则是第一次调用,需要初始化堆
		if( pxEnd == NULL )
		{
			prvHeapInit();
		}
		else
		{
			mtCOVERAGE_TEST_MARKER();
		}
		/* Check the requested block size is not so large that the top bit is
		set.  The top bit of the block size member of the BlockLink_t structure
		is used to determine who owns the block - the application or the
		kernel, so it must be free. */
		//xBlockAllocatedBit = 0x8000_0000;
		//待分配的内存不能大于0x7FFF_FFFF,否则失败
		if( ( xWantedSize & xBlockAllocatedBit ) == 0 )
		{
			/* The wanted size is increased so it can contain a BlockLink_t
			structure in addition to the requested amount of bytes. */
			if( xWantedSize > 0 )
			{
			    //加上管理结构体占用大小
				xWantedSize += xHeapStructSize;
				/* Ensure that blocks are always aligned to the required number
				of bytes. */
				//xWantedSize大小进行字节对齐调整
				if( ( xWantedSize & portBYTE_ALIGNMENT_MASK ) != 0x00 )
				{
					/* Byte alignment required. */
					xWantedSize += ( portBYTE_ALIGNMENT - ( xWantedSize & portBYTE_ALIGNMENT_MASK ) );
					configASSERT( ( xWantedSize & portBYTE_ALIGNMENT_MASK ) == 0 );
				}
				else
				{
					mtCOVERAGE_TEST_MARKER();
				}
			}
			else
			{
				mtCOVERAGE_TEST_MARKER();
			}
            //xWantedSize大于0且小于等于此时还剩字节数才能往下申请
			if( ( xWantedSize > 0 ) && ( xWantedSize <= xFreeBytesRemaining ) )
			{
				/* Traverse the list from the start	(lowest address) block until
				one	of adequate size is found. */
				//pxPreviousBlock指向头链表
				pxPreviousBlock = &xStart;
				//pxBlock指向头链表的下一个即第一个空闲块
				pxBlock = xStart.pxNextFreeBlock;
				//开始遍历找到第一个比xWantedSize大的空闲块
				while( ( pxBlock->xBlockSize < xWantedSize ) && ( pxBlock->pxNextFreeBlock != NULL ) )
				{
				    //pxPreviousBlock保存空闲块的上一个
					pxPreviousBlock = pxBlock;
					pxBlock = pxBlock->pxNextFreeBlock;
				}
				/* If the end marker was reached then a block of adequate size
				was	not found. */
				//遍历完成pxBlock != pxEnd说明找到符合的空闲块
				if( pxBlock != pxEnd )
				{
					/* Return the memory space pointed to - jumping over the
					BlockLink_t structure at its start. */
					//返回给用户的内存地址要跳过管理结构体占用的内存大小
					pvReturn = ( void * ) ( ( ( uint8_t * ) pxPreviousBlock->pxNextFreeBlock ) + xHeapStructSize );
					/* This block is being returned for use so must be taken out
					of the list of free blocks. */
					//因为pxPreviousBlock->pxNextFreeBlock指向的空闲块被分配了,
					//所以要把pxPreviousBlock->pxNextFreeBlock指向的空闲块移除出去,
					//也就是pxPreviousBlock->pxNextFreeBlock指向pxBlock->pxNextFreeBlock
					//也就是跳过分配出去的那个块
					pxPreviousBlock->pxNextFreeBlock = pxBlock->pxNextFreeBlock;
					/* If the block is larger than required it can be split into
					two. */
					//这里判断,
					//如果将要分配出去的内存块大小xBlockSize比分配出去的还要大heapMINIMUM_BLOCK_SIZE(2倍管理结构体)
					//为了节约就把再分成2块,一块返回给用户,
					//一块构造一个新的空闲管理结构体后插入空闲链表
					if( ( pxBlock->xBlockSize - xWantedSize ) > heapMINIMUM_BLOCK_SIZE )
					{
						/* This block is to be split into two.  Create a new
						block following the number of bytes requested. The void
						cast is used to prevent byte alignment warnings from the
						compiler. */
						//注意这里xWantedSize是管理结构体和和真正需要字节数之和
						//所以是在pxBlock基础上偏移xWantedSize作为新的管理结构体
						pxNewBlockLink = ( void * ) ( ( ( uint8_t * ) pxBlock ) + xWantedSize );
						configASSERT( ( ( ( size_t ) pxNewBlockLink ) & portBYTE_ALIGNMENT_MASK ) == 0 );
						/* Calculate the sizes of two blocks split from the
						single block. */
						//pxNewBlockLink新的管理结构体大小
						//是待分配pxBlock->xBlockSize-xWantedSize
						pxNewBlockLink->xBlockSize = pxBlock->xBlockSize - xWantedSize;
						//更新pxBlock->xBlockSize大小为xWantedSize
						pxBlock->xBlockSize = xWantedSize;
						/* Insert the new block into the list of free blocks. */
						//把新构造的空闲管理结构体按结构体地址升序插入到空闲链表
						prvInsertBlockIntoFreeList( pxNewBlockLink );
					}
					else
					{
						mtCOVERAGE_TEST_MARKER();
					}
					//还剩空闲字节数要减去分配出去的
					xFreeBytesRemaining -= pxBlock->xBlockSize;
					//更新历史最小剩余字节数
					if( xFreeBytesRemaining < xMinimumEverFreeBytesRemaining )
					{
						xMinimumEverFreeBytesRemaining = xFreeBytesRemaining;
					}
					else
					{
						mtCOVERAGE_TEST_MARKER();
					}
					/* The block is being returned - it is allocated and owned
					by the application and has no "next" block. */
					//xBlockSize最高位置1表示被这块内存被分配出去
					pxBlock->xBlockSize |= xBlockAllocatedBit;
					//所以管理结构体的next要指向NULL
					pxBlock->pxNextFreeBlock = NULL;
				}
				else
				{
					mtCOVERAGE_TEST_MARKER();
				}
			}
			else
			{
				mtCOVERAGE_TEST_MARKER();
			}
		}
		else
		{
			mtCOVERAGE_TEST_MARKER();
		}
		traceMALLOC( pvReturn, xWantedSize );
	}//解挂调度器
	( void ) xTaskResumeAll();
    //如果定义了分配失败钩子函数,分配失败则执行钩子函数
	#if( configUSE_MALLOC_FAILED_HOOK == 1 )
	{
		if( pvReturn == NULL )
		{
			extern void vApplicationMallocFailedHook( void );
			vApplicationMallocFailedHook();
		}
		else
		{
			mtCOVERAGE_TEST_MARKER();
		}
	}
	#endif
//返回给用户
	configASSERT( ( ( ( size_t ) pvReturn ) & ( size_t ) portBYTE_ALIGNMENT_MASK ) == 0 );
	return pvReturn;
}

内存堆初始化

static void prvHeapInit( void )
{
BlockLink_t *pxFirstFreeBlock;
uint8_t *pucAlignedHeap;
size_t uxAddress;
size_t xTotalHeapSize = configTOTAL_HEAP_SIZE;
	/* Ensure the heap starts on a correctly aligned boundary. */
	uxAddress = ( size_t ) ucHeap;
    //这里进行字节对齐
	if( ( uxAddress & portBYTE_ALIGNMENT_MASK ) != 0 )
	{
		uxAddress += ( portBYTE_ALIGNMENT - 1 );
		uxAddress &= ~( ( size_t ) portBYTE_ALIGNMENT_MASK );
		//此时xTotalHeapSize表示管理的总内存字节数
		xTotalHeapSize -= uxAddress - ( size_t ) ucHeap;
	}
    //pucAlignedHeap指向对齐后首址
	pucAlignedHeap = ( uint8_t * ) uxAddress;
	/* xStart is used to hold a pointer to the first item in the list of free
	blocks.  The void cast is used to prevent compiler warnings. */
	//初始化头链表
	xStart.pxNextFreeBlock = ( void * ) pucAlignedHeap;
	xStart.xBlockSize = ( size_t ) 0;

	/* pxEnd is used to mark the end of the list of free blocks and is inserted
	at the end of the heap space. */
	//uxAddress此时指向管理内存最后
	uxAddress = ( ( size_t ) pucAlignedHeap ) + xTotalHeapSize;
	//退回一个BlockLink_t(字节对齐后)大小字节数
	uxAddress -= xHeapStructSize;
	//再次字节对齐
	uxAddress &= ~( ( size_t ) portBYTE_ALIGNMENT_MASK );
	//初始化尾链表
	pxEnd = ( void * ) uxAddress;
	pxEnd->xBlockSize = 0;
	pxEnd->pxNextFreeBlock = NULL;
	/* To start with there is a single free block that is sized to take up the
	entire heap space, minus the space taken by pxEnd. */
	//初始化第一个空闲块
	pxFirstFreeBlock = ( void * ) pucAlignedHeap;
	//第一个空闲块字节数=uxAddress(此时值=pxEnd) - pxFirstFreeBlock(此时值=pucAlignedHeap)
	pxFirstFreeBlock->xBlockSize = uxAddress - ( size_t ) pxFirstFreeBlock;
	//第一个空闲块指向尾节点
	pxFirstFreeBlock->pxNextFreeBlock = pxEnd;
	/* Only one block exists - and it covers the entire usable heap space. */
	//更新历史还剩最少空闲字节数
	xMinimumEverFreeBytesRemaining = pxFirstFreeBlock->xBlockSize;
	//更新实时还剩字节数
	xFreeBytesRemaining = pxFirstFreeBlock->xBlockSize;
	/* Work out the position of the top bit in a size_t variable. */
	//这里sizeof( size_t ) = 4,heapBITS_PER_BYTE=8,表示1字节有8bit
	//xBlockAllocatedBit = 1<<(4*8-1) = 0x8000_0000;
	//FreeRTOS用xBlockSize最高位来标记此内存块是否空闲
	//所以heap4最大只能管理0x7FFF_FFFF字节内存
	xBlockAllocatedBit = ( ( size_t ) 1 ) << ( ( sizeof( size_t ) * heapBITS_PER_BYTE ) - 1 );
}

初始化后的示意图如下
注意xEnd结构体占用的时堆内存

把新构造的结构体插入空闲链表

static void prvInsertBlockIntoFreeList( BlockLink_t *pxBlockToInsert )
{
BlockLink_t *pxIterator;
uint8_t *puc;
	/* Iterate through the list until a block is found that has a higher address
	than the block being inserted. */
	//这里是根据内存块的地址大小来迭代寻找和pxBlockToInsert相邻的前一个空闲的内存块
	for( pxIterator = &xStart; pxIterator->pxNextFreeBlock < pxBlockToInsert; pxIterator = pxIterator->pxNextFreeBlock )
	{
		/* Nothing to do here, just iterate to the right position. */
	}
	/* Do the block being inserted, and the block it is being inserted after
	make a contiguous block of memory? */
	//这里判断pxBlockToInsert是否能与pxBlockToInsert相邻的前一个空闲的内存块合并
	puc = ( uint8_t * ) pxIterator;
	if( ( puc + pxIterator->xBlockSize ) == ( uint8_t * ) pxBlockToInsert )
	{   //这里做向前合并,xBlockSize相加
		pxIterator->xBlockSize += pxBlockToInsert->xBlockSize;
		//pxBlockToInsert指向pxIterator
		pxBlockToInsert = pxIterator;
	}
	else
	{
		mtCOVERAGE_TEST_MARKER();
	}
	/* Do the block being inserted, and the block it is being inserted before
	make a contiguous block of memory? */
	//这里再判断是否能与后一个内存块合并
	puc = ( uint8_t * ) pxBlockToInsert;
	if( ( puc + pxBlockToInsert->xBlockSize ) == ( uint8_t * ) pxIterator->pxNextFreeBlock )
	{   //这里做向后合并,如果要合并的后向不是pxEnd
		if( pxIterator->pxNextFreeBlock != pxEnd )
		{  //这里把后项合入到pxBlockToInsert
			/* Form one big block from the two blocks. */
			pxBlockToInsert->xBlockSize += pxIterator->pxNextFreeBlock->xBlockSize;
			//pxBlockToInsert的下一个指向后项指向的空闲块
			pxBlockToInsert->pxNextFreeBlock = pxIterator->pxNextFreeBlock->pxNextFreeBlock;
		}
		else//如果后项是pxEnd就不能合并,指向pxEnd
		{
			pxBlockToInsert->pxNextFreeBlock = pxEnd;
		}
	}
	else//不相邻就只能插入链表
	{
		pxBlockToInsert->pxNextFreeBlock = pxIterator->pxNextFreeBlock;
	}
	/* If the block being inserted plugged a gab, so was merged with the block
	before and the block after, then it's pxNextFreeBlock pointer will have
	already been set, and should not be set here as that would make it point
	to itself. */
	//这里如果不等,说明没有做前向合并操作,
	//需要更新下链表插入
	if( pxIterator != pxBlockToInsert )
	{
		pxIterator->pxNextFreeBlock = pxBlockToInsert;
	}
	else
	{
		mtCOVERAGE_TEST_MARKER();
	}
}

释放

void vPortFree( void *pv )
{
uint8_t *puc = ( uint8_t * ) pv;
BlockLink_t *pxLink;
	if( pv != NULL )
	{
		/* The memory being freed will have an BlockLink_t structure immediately
		before it. */
		//偏移回地址
		puc -= xHeapStructSize;
		/* This casting is to keep the compiler from issuing warnings. */
		pxLink = ( void * ) puc;
		/* Check the block is actually allocated. */
		//检查这个内存块是否是heap4之前分配的
		configASSERT( ( pxLink->xBlockSize & xBlockAllocatedBit ) != 0 );
		configASSERT( pxLink->pxNextFreeBlock == NULL );
		if( ( pxLink->xBlockSize & xBlockAllocatedBit ) != 0 )
		{
			if( pxLink->pxNextFreeBlock == NULL )
			{
				/* The block is being returned to the heap - it is no longer
				allocated. */
				//把分配的xBlockSize最高位标记清除
				pxLink->xBlockSize &= ~xBlockAllocatedBit;
                //挂起调度器
				vTaskSuspendAll();
				{
					/* Add this block to the list of free blocks. */
				   //更新剩余内存数
					xFreeBytesRemaining += pxLink->xBlockSize;
					traceFREE( pv, pxLink->xBlockSize );
					//插入空闲内存链表
					prvInsertBlockIntoFreeList( ( ( BlockLink_t * ) pxLink ) );
				}//解挂调度器
				( void ) xTaskResumeAll();
			}
			else
			{
				mtCOVERAGE_TEST_MARKER();
			}
		}
		else
		{
			mtCOVERAGE_TEST_MARKER();
		}
	}
}

还剩空闲字节数

size_t xPortGetFreeHeapSize( void )
{
	return xFreeBytesRemaining;
}

历史剩余最小字节数

size_t xPortGetMinimumEverFreeHeapSize( void )
{
	return xMinimumEverFreeBytesRemaining;
}

适用范围、特点

heap4在heap2基础上加入了合并内存碎片算法,把相邻的内存碎片合并成一个更大的块、且xEnd结构体占用的是内存堆空间。
heap2的管理结构体链表是按照xBlockSize大小升序串起来,所以空闲块插入也是按照空闲块大小升序插入,而heap4管理结构体是按照空闲块管理结构体地址大小升序串起来,这样做是为了判断地址是否连续,若连续则能进行碎片合并,且用xBlockSize的最高为标记是否是已经分配的。

以上就是FreeRTOS动态内存分配管理heap_4示例的详细内容,更多关于FreeRTOS动态内存分配的资料请关注我们其它相关文章!

(0)

相关推荐

  • FreeRTOS实时操作系统的任务创建与任务切换

    目录 任务控制块数据结构 任务创建函数 定义就绪表 就绪表初始化 启动调度器 任务切换 任务控制块数据结构 任务控制块数据结构在task.c声明 typedef struct tskTaskControlBlock { volatile StackType_t * pxTopOfStack; //栈顶指针 ListItem_t xStateListItem; //任务节点 StackType_t * pxStack; //任务栈起始地址 char pcTaskName[configMAX_TAS

  • FreeRTOS实时操作系统空闲任务的阻塞延时实现

    目录 什么是阻塞延时.为什么需要空闲任务 空闲任务的实现 阻塞延时的实现 xTicksToDelay 递减 SysTick初始化 仿真 什么是阻塞延时.为什么需要空闲任务 RTOS中的延时叫阻塞延时,即任务需要延时时,任务会放弃cpu使用权,cpu转而去做其他的事,当任务延时时间到后,任务重新请求获得cpu使用权.但当所有的任务都处于阻塞后,为了不让cpu空闲没事干就需要一个空闲任务让cpu干活. 空闲任务的实现 空闲任务实现和创建普通任务没区别,空闲任务在调用vTaskStartSchedul

  • FreeRTOS实时操作系统的多优先级实现

    目录 如何实现任务多优先级 软件通用方法和硬件指令方法 如何实现任务多优先级 FreeRTOS中,数字优先级越小,逻辑优先级也越小,空闲任务优先级为0.List_t pxReadyTasksLists[configMAX_PRIORITIES]是数组,数组下标代表任务优先级,任务创建是根据设置的任务优先级插入到对应下标的列表根节点上,如下. 要支持多优先级,就是再任务切换时让pxCurrentTCB指向最高优先级的TCB即可,之前时手动再任务1.任务2来回切换,现在问题就是怎么找到优先级最高的就

  • FreeRTOS实时操作系统的列表与列表项操作示例

    目录 前言 列表项数据结构 列表项初始化 列表数据结构 将列表项按照升序排列插入到列表 将列表项从列表删除 前言 FreeRTOS列表与列表项其实就是链表和节点,在list.c和list.h实现 列表项数据结构 //列表项数据结构 typedef struct xLIST_ITEM { TickType_t xItemValue; //辅助值,用作节点做顺序排序 struct xLIST_ITEM * pxNext;//后继指针 struct xLIST_ITEM * pxPrevious;//

  • FreeRTOS动态内存分配管理heap_2示例

    目录 heap_2.c 内存堆管理 分配 初始化内存堆 把新构造的结构体插入空闲链表 释放 还剩空闲字节数 适用范围.特点 heap_2.c 内存堆管理 heap_2和heap_1一样是开辟一个大数组作为堆空间供用户使用,但是采用单项不循环链表来管理内存的分配释放,主要思想是用链表把内存块串起来,数据结构如下 /* Define the linked list structure. This is used to link free blocks in order of their size.

  • FreeRTOS动态内存分配管理heap_1示例

    目录 动态内存管理 heap_1.c 内存堆管理 实际可用数组字节数 分配 释放 还剩空闲字节数 动态内存管理 FreeRTOS提供5种动态内存管理策略,分别为heap_1到heap_5,源码在FreeRTOS/Source/portable/MemMang下,本质是对一个或者多个大数组进行操作来对系统提供内存的申请.释放(有的策略没有)功能.下面先看看heap_1是怎么做的. heap_1.c 内存堆管理 大数组在哪里 /* Allocate the memory for the heap.

  • FreeRTOS实时操作系统支持时间片示例详解

    目录 什么是时间片 时间片实现关键 taskSELECT_HIGHEST_PRIORITY_TASK() taskRESET_READY_PRIORITY() 什么是时间片 时间片就是同一个优先级下可以有多个任务,每个任务轮流地享有相同的 CPU 时间, 享有 CPU 的时间我们叫时间片.在 RTOS 中,最小的时间单位为一个 tick,即 SysTick 的中断周期,与其说 FreeRTOS 支持时间片,倒不如说它的时间片就是正常的任务调度. 时间片实现关键 时间片实现关键在这两个宏. tas

  • FreeRTOS实时操作系统的内存管理分析

    目录 1.heap_1.c 功能简介: 2.heap_2.c 功能简介: 3.heap_3.c 功能简介: 4.heap_4.c 功能简介: 5.heap_5.c(V8.1.0新增) 前言 本文介绍内存管理的基础知识,详细源码分析见< FreeRTOS内存管理示例分析> FreeRTOS提供了几个内存堆管理方案,有复杂的也有简单的.其中最简单的管理策略也能满足很多应用的要求,比如对安全要求高的应用,这些应用根本不允许动态内存分配的. FreeRTOS也允许你自己实现内存堆管理,甚至允许你同时使

  • FreeRTOS动态内存分配管理heap_4示例

    目录 heap_4.c 内存堆管理 数据结构如下 分配 内存堆初始化 把新构造的结构体插入空闲链表 释放 还剩空闲字节数 历史剩余最小字节数 适用范围.特点 heap_4.c 内存堆管理 heap_4也是用链表来管理,但是链表头用的是结构体,链表尾用的是指针,链表尾占用ucHeap内存 数据结构如下 /* Define the linked list structure. This is used to link free blocks in order of their memory addr

  • FreeRTOS动态内存分配管理heap_5示例

    目录 heap_5.c vPortDefineHeapRegions 常见问题 heap_5.c heap5与heap4分配释放算法完全相同,只是heap5支持管理多块不连续的内存,本质是将多块不连续内存用链表串成一整块内存,再用heap4算法来分配释放.若使用heap5则在涉及到分配释放的函数调用时要先调用vPortDefineHeapRegions把多块不连续内存串成一块初始化. vPortDefineHeapRegions 此函数原型 void vPortDefineHeapRegions

  • C语言编程C++动态内存分配示例讲解

    目录 动态内存管理 为什么存在动态内存分配 动态内存函数的介绍 malloc申请空间和free释放空间 有借有还 free释放内存 calloc申请内存 realloc调整动态内存的大小 realloc使用的注意事项 当然realloc也可以直接开辟空间 常见的动态内存错误 1.对NULL指针的解引用操作 2.对动态开辟空间的越界访问 3.对非动态开辟内存使用free释放 4.使用free释放一块动态内存开辟的一部分 5.对同一块动态内存多次释放 6.动态开辟内存忘记释放(内存泄漏) 几个面试题

  • C语言编程动态内存分配常见错误全面分析

    目录 前言:为什么存在动态内存分配? 一.动态内存函数 1.malloc和free函数 2.calloc函数 3.realloc函数 二.常见错误 1.对NULL指针解引用 2.对动态开辟空间的越界访问 3.对非动态开辟使用free函数 4.使用free释放一块动态内存开辟内存的一部分 5.对同一块空间多次释放 6.动态开辟内存忘记释放 总结 前言:为什么存在动态内存分配? 我们已经掌握的内存开辟方式如下 int a=10;//在栈空间上开辟4字节 char arr[10]={0};//在栈空间

  • C语言动态内存分配的详解

    C语言动态内存分配的详解 1.为什么使用动态内存分配 数组在使用的时候可能造成内存浪费,使用动态内存分配可以解决这个问题. 2. malloc和free C函数库提供了两个函数,malloc和free,分别用于执行动态内存分配和释放. (1)void *malloc(size_t size); malloc的参数就是需要分配的内存字节数.malloc分配一块连续的内存.如果操作系统无法向malloc提供更多的内存,malloc就返回一个NULL指针. (2)void free(void *poi

  • 动态内存分配导致影响Javascript性能的问题

    内存分配对性能的影响是很大的,分配内存本身需要时间,垃圾回收器回收内存也需要时间,所以应该尽量避免在堆里分配内存.不过直到最近优化HoLa cantk时,我才深刻的体会到内存分配对性能的影响,其中有一个关于arguments的问题挺有意思,写在这里和大家分享一下. 我要做的事情是用webgl实现canvas的2d API(这个话题本身也是挺有意思的,有空我们再讨论),drawImage是一个重要的函数,游戏会频繁的调用它,所以它的性能至关重要.drawImage的参数个数是可变的,它有三种形式:

  • C语言动态内存分配函数的实现

    在C中我们开辟内存空间有两种方式 : 1.静态开辟内存 :例如: int a;int b[10]; 这种开辟内存空间的特点是 所开辟的内存是在栈中开辟的固定大小的 ,如a是4字节 ,数组b是40字节 ,并且数组在申明时必须指定其长度 , 如果是全局数组的话,内存是在编译时分配好的,如果是局部变量数组的话,运行时在栈上静态分配内存.不管是全局数组还是局部数组,它们都有一个特点,那就是数组大小是确定的,是代码中写死的.那如果我们想在程序运行时才确定一个数组的大小 , 前两种在栈上分配内存的方法显然是

  • Android NDK开发(C语言--动态内存分配)

    1.C 内存管理函数 C 语言为内存的分配和管理提供了几个函数.这些函数可以在 <stdlib.h> 头文件中找到. 序号 函数和描述 1 void calloc(int num, int size); 在内存中动态地分配 num 个长度为 size 的连续空间,并将每一个字节都初始化为 0.所以它的结果是分配了 numsize 个字节长度的内存空间,并且每个字节的值都是0. 2 void free(void *address); 该函数释放 address 所指向的内存块,释放的是动态分配的

随机推荐