C-动态内存管理-动态内存管理
发布时间:2025-06-24 14:08:50 作者:北方职教升学中心 阅读量:472
目录。
为什么要有动态内存管理?
二、malloc和free。
(2.1)malloc。
(2.2.#xfff09;free。
三、calloc和realloc。
(3.1)calloc。
(3.2)realloc。
四、动态内存常见错误(例子都是错误的演示)
(4.1)对空指针的解引操作。
(4.2越界访问动态开放空间。
(4.3)free用于非动态开发内存。
(4.4使用free释放动态开放内存的一部分。
(4.5多次freee地打开同一块动态内存。
(4.6忘记释放动态开启内存(内存泄漏)
五、动态内存经典笔试题分析。
(5.1)题目1。
(5.2)题目2。
(5.3)题目3。
(5.4)题目4。
六、柔性数组。
(6.1柔性数组的特点。
(6.2柔性数组的优点。
七、总结C//C++中程序内存区域划分。
为什么要有动态内存管理?
正常情况下,我们可以在栈上创建一个变量或数组来打开空间,例如:
但上述开放空间的开放空间⽅有两个特点:
• 空间开辟⼤⼩是固定的。
• 数组在申报时,必须指定数组⻓度,数组空间⼀旦确定了⼤⼩不能调整。
但是对空间的需求,不仅仅是上述情况。有时我们需要的空间⼤⼩在程序运⾏只有这样才能知道。
道,当编译数组时,打开空间⽅式就不能满⾜了。C语⾔引⼊开发动态内存,让程序员⾃⼰可以申请和释放空间,就⽐较灵活了。
二、malloc和free。
(2.1)malloc。
C语⾔提供了⼀一个动态内存开辟函数,以下:(该函数在头文件中包含stdlibib.h里)
向内存申请此函数⼀块连续可⽤空间,并返回指向这个空间的指针。具有以下特点:
• 如果开放成功则返回⼀指向开放空间的指针。
• 如果开启失败则返回⼀个 NULL 指针,因此,malloc的返回值⼀一定要做检查。 • 返回值的类型是 void* ,因此,malloc函数不知道开放空间的类型,具体在使⽤的时候使⽤者⾃。
⼰来决定。
• 如果参数 size 0,malloc⾏标准是未定义的,这取决于编译器。
例如,如今,我们想开辟一个存储int类型数据的空间:
(2.2#xff09;free。
C语⾔提供了另外⼀函数free,专⻔是⽤释放和回收动态内存,函数原型如下༚
free函数⽤释放动态开放的内存。xff1具有以下特点a;
• 如果参数 ptr 指向空间不是动态开放的,那free函数⾏为未定义。 。
• 如果参数 ptr NULL指针༌函数什么都不做。
freee和malloc一样都声明在 stdlib.h 头⽂件中。
例如:
运行效果:
三、calloc和realloc。
(3.1)calloc。
C语⾔还提供了⼀个函数叫 calloc , calloc 函数也⽤动态内存分配。原型如下:
该函数的特性:
• 函数的功能是 num 个⼤⼩为 size 的元素开辟⼀块空间,并将空间的每个字节初始化为0。 。
• 与函数 malloc 区别只在于 calloc 申请空间的每个字节将在返回地址之前初始化为0。
例子:
运行效果:
因此,如果我们要求初始化应用内存空间的内容,那么可以很⽅便的使⽤calloc函数完成任务。
(3.2)realloc。
函数原型如下༚
该函数具有以下特点a;
• realloc函数的出现使得动态内存管理更加灵活。
• 有时候我们会发现过去申请的空间太大了⼩,有时候我们⼜你会觉得申请空间太大了⼤,在合理的时间内存,我们⼀会对内存进行记忆⼤⼩灵活调整。那 realloc 函数可以为动态开启内存⼤⼩的调整。
。
• ptr 内存地址需要调整。
• size 调整后的新⼤⼩。
• 返回值是调整后内存的起始位置。
• 这个函数调整了原内存空间⼤⼩的基础c;将原始内存中的数据移动到一个新的空间。
• Realloc在调整内存空间时有两种情况:
◦ 情况1:后面有原始空间⾜够⼤的空间。
◦ 情况2༚之后没有原有的空间⾜够⼤的空间。
如图:
情况1的时候,要扩展内存,直接在原始内存后添加空间,没有发送原始空间数据⽣变化。当情况为2时,之后没有原有的空间⾜空间充足的时间,扩展的⽅法是:另找堆空间⼀个合适⼤⼩使用连续空间⽤,将原始空间数据复制到新空间并释放原始空间。函数返回是这样的⼀新的内存地址。由于上述两种情况,realloc函数使⽤就要注意⼀些。例子:
四、动态内存常见错误(例子都是错误的演示)
(4.1)对空指针的解引操作。
例如:
(4.2越界访问动态开放空间。
(4.3)freee用于非动态开放内存。
(4.4使用free释放动态开放内存的一部分。
(4.5多次freee地打开同一块动态内存。
(4.6忘记释放动态开启内存(内存泄漏)
忘记释放不再使用⽤动态开放空间会导致内存泄漏。
记住:动态开放空间⼀必须释放,并正确释放。
五、动态内存经典笔试题分析。
(5.1)题目1。
运行结果:
从上述操作结果可以看出,程序已经崩溃。
说明:
通过调试可以发现,作为函数GetMemory的参数,指针str没有传递地址,因此,形参的变化不会影响实参,即p的变化不会影响str,函数结束时,str仍然空,因此,在调用strcpy函数时会报错。
(5.2)题目2。
运行效果:
说明:随着函数的结束,Getmemory函数中开放的数组空间将被销毁,虽然地址已经返回,但是空间已经销毁了,此时,使用str访问这个空间,内容是随机的。
(5.3)题目3。
运行效果:
说明:随着函数的结束,动态开放的空间不会被销毁,在Test中,将Str的地址传输到Getmemory函数,因此,形参可以影响实参,也就是说,str指向malloc申请的空间,因此,strcpy函数可以正常使用,打印没有问题,但是这里忘记释放动态开放的空间,会导致内存泄漏。
(5.4)题目4。
(5.4)题目4.
运行效果:说明:
虽然这里打印成功但是这个代码有问题,str指向的空间已被释放,但是free函数不会空指针,所以这里有一个被销毁的空间。
六、柔性数组。
C99中结构的最后⼀未知允许个元素⼤⼩数组,这就叫做『柔性数组』成员。例如:
有些编译器会报错⽆法编译可以改为:
(6.1柔性数组的特点。
• 结构中的柔性数组成员⾯必须⾄少⼀其他成员。
• sizeof 返回的结构⼤⼩不包括柔性数组的内存。
• 结构包含柔性数组成员⽤malloc()函数进⾏内存动态分配,而且应该分配内存⼤于结构的⼤⼩,适应柔性数组的预期⼤⼩。
例如:
代码1:
(6.2柔性数组的优点。
上述的 type_a 结构也可以设计为下⾯结构,同样的效果也可以完成。
代码2:
上述代码1和代码2 可完成相同的功能,但是⽅法1的实现有两个好处:
第⼀好处是:⽅大便内存释放。
假如我们的代码在那里⼀个给别⼈⽤在函数中c;你在⾥⾯做了⼆二次内存分配并将整个结构返还给它⽤⼾。⽤⼾调⽤free可以释放结构体,但是⽤⼾我不知道这个结构中的成员也需要free,所以你不能指望⽤⼾发现这件事。所以,如果我们把结构的内存和成员想要的内存放在一起⼀次性分配,并返回给⽤⼾⼀个体结构指针,⽤⼾做⼀次free可以释放所有内存。
第⼆好处是:这有利于访问速度。
连续内存有利于提升⾼访问速度,也有助于减少内存碎片⽚。
七、总结C//C++中程序内存区域划分。
C/C++程序内存分配⼏各区域:
1. 栈区(stack):在执⾏函数时,函数中的局部变量存储单元可以在栈上创建,函数执⾏这些存储单元在结束时⾃动被释放。堆栈内存分配操作中处理器内置的指令集中,效率很⾼,但内存容量的分配是有限的。栈区主要存放运输⾏函数⽽局部变量、函数参数、返回数据、返回地址等。
2. 堆区(heap):⼀程序员通常会分配和释放#xff0c;如果程序员不释放OS可以在程序结束时回收。分配⽅。
类似链表的类型。