C动态内存那些事

为什么存在动态内存分配?

首先,动态内存分配是计算机中一种重要的内存管理方法,它主要解决了静态内存分配无法灵活应对变化需求的问题。以下是几个存在动态内存分配的原因:

  1. 灵活性:动态内存分配允许程序在运行时根据需要动态地分配和释放内存。这对于需要动态改变内存使用情况的应用来说非常重要,比如动态数据结构、动态数组或者不确定大小的数据等。

  2. 节省内存:动态内存分配可以根据需求精确地分配所需大小的内存,避免了静态分配过多内存的浪费,并且可以回收不再使用的内存,提高内存的利用率。

  3. 动态数据结构支持:一些常见的数据结构,比如链表、树等,需要根据运行时的需求动态地分配内存来存储数据。动态内存分配可以满足这些数据结构的需要,使得程序能够更灵活地处理各种数据。

  4. 多任务支持:操作系统中的多任务环境下,每个任务需要独立的内存空间来存储自己的数据。动态内存分配允许每个任务根据需要独立分配内存,从而实现任务间的数据隔离,提高系统的安全性和可靠性。

其次值得注意的是,动态内存分配也需要注意管理好分配和释放内存的过程,避免内存泄漏或者其他内存管理问题。

动态内存管理函数

void* malloc(size_t size)

成功返回:开辟好空间的首地址,不会初始化空间内容,当程序退出时,还给操作系统,,当程序不退出,动态申请的内存,不会主动释放的

错误返回:NULL指针------NULL指针不可以使用,所以要对malloc返回的指针做检查

向内存申请一块连续可以的空间,并返回指向这块空间的指针

void* calloc(size_t num, size_t size);
  • num:要分配的元素个数。
  • size:每个元素的大小。
  • calloc函数会分配num * size字节的内存空间,并将所分配的内存块中的每个字节都初始化为0。这与使用malloc分配内存后手动初始化为0的效果相同。
void* realloc(void *ptr, size_t size);
  • ptr:指向之前分配的内存块的指针。(简单来说就是提前申请过的一块内存空间首地址)

  • size:要重新分配的内存块的大小。

  • realloc函数可以用来扩大或缩小已分配内存的大小。当ptr为NULL时,realloc的行为与malloc相同,即分配一块新的内存空间。当ptr不为NULL时,realloc会尝试重新分配ptr指向的内存块,将其大小调整为size所指定的大小。

  • (1)当新的大小size小于或等于原内存块的大小时,realloc会尝试缩小内存块的大小,并返回指向缩小后内存的指针。可能会丢失部分原有数据。

  • (2)当新的大小size大于原内存块的大小时,realloc会尝试扩大内存块的大小。如果扩大成功,会返回指向扩大后内存的指针。扩大后的新增内存区域的内容是未定义的。如果扩大失败,会保持原有内存块不变,并返回NULL。

  • (3)当ptr为NULL时,realloc会等同于malloc(size),即分配一块新的大小为size的内存块,并返回指向该内存块的指针。

由于这个函数很特别,下面通过一段代码结合画的内存图,方便大家理解

int main()

{

int* p=(int*)malloc(40);

if(p==NULL)

{

perror("malloc");

return 1;

}

int i=0;

for(i=0;i<10;i++)

{

p[i]=i+1;

}

p=realloc(p,80);

return 0;

}

下面是申请成功的情况,红色区域代码后边有占用的数据

第二种情况步骤

1.开辟新空间

2.将旧空间数据拷贝到新空间

3.释放旧空间

4.返回新空间起始地址

还有一种是内存申请失败的情况会造成内存泄漏

为了避免内存泄漏可以把

p=realloc(p,80);这段代码替换成

int* ptr=(int*)realloc(p,80);

if(ptr!=NULL)

{

p=ptr;

ptr=NULL;

}

else

{

perror("realloc");

return 1;

}

//释放

free(p);

void* free(void* ptr)

释放掉ptr所指的内存空间

相关推荐
黄焖鸡能干四碗5 分钟前
智慧教育,智慧校园,智慧安防学校建设解决方案(PPT+WORD)
java·大数据·开发语言·数据库·人工智能
神里流~霜灭12 分钟前
(C++)数据结构初阶(顺序表的实现)
linux·c语言·数据结构·c++·算法·顺序表·单链表
一只乔哇噻33 分钟前
java后端工程师进修ing(研一版 || day41)
java·开发语言·学习·算法
钮钴禄·爱因斯晨43 分钟前
深入剖析LLM:从原理到应用与挑战
开发语言·人工智能
六点半8881 小时前
【C++】C++11 篇二
开发语言·c++
DDDDDDDRDDR1 小时前
C++容器:list
开发语言·c++·stl
Elnaij1 小时前
从C++开始的编程生活(7)——取地址运算符重载、类型转换、static成员和友元
开发语言·c++
chen_ever1 小时前
golang之go modules
开发语言·后端·golang
郝学胜-神的一滴1 小时前
Effective Modern C++ 条款26:避免在通用引用上重载
开发语言·c++·程序人生
草莓熊Lotso2 小时前
【C++】递归与迭代:两种编程范式的对比与实践
c语言·开发语言·c++·经验分享·笔记·其他