文章目录
- 🍎常用的内存操作函数
- 🎂传统内存管理的弊端
- ⭐弊端一
- ⭐弊端二
- ⭐弊端三
- ⭐弊端四
- 🚀解决方法
- ⭐内存管理工具选择
- ⭐内存池技术
🍎常用的内存操作函数
- void *malloc(size_t size);
- void *calloc(size_t nmemb, size_t size);
- void *realloc(void *ptr, size_t size);
- void free(void *ptr);
malloc
在内存的动态存储区中分配一块长度为size字节的连续区域返回该区域的首地址.
calloc
与malloc相似,参数size为申请地址的单位元素长度,nmemb为元素个数,即在内存中申请nmemb*size字节大小的连续地址空间.内存会初始化0
realloc
给一个已经分配了地址的指针重新分配空间,参数ptr为原有的空间地址,newsize是重新申请的地址长度.ptr 若为NULL,它就等同于 malloc.
🎂传统内存管理的弊端
⭐弊端一
高并发下较小内存块使用导致系统调用频繁,这样是会影响系统的执行效率
这句话是什么意思呢?====》malloc、calloc以及realloc其实本质上就是进行系统调用,而如果我们当前的系统要进行频繁的小内存的分配和使用那么就等同于频繁的进行系统调用,那么系统的运行时间自然就变长。
来看看chatgpt的回答:
就像下面的代码一样,如果频繁地使用malloc、free,那么这个程序的时间会很慢,当然,后续我会介绍内存池来分配和释放内存,和下面的方式进行速度比较,到时候就知道高性能内存池有多牛啦
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>#define BLOCK_SIZE 16 //每次分配内存块大小
#define TEST_COUNT 1024int main(int argc, char **argv)
{int i = 0, k = 0;int use_free = 0;{char * ptr[TEST_COUNT];for(k = 0; k< 1024 * 500; k++){for(i = 0; i < TEST_COUNT ; i++){ptr[i] = malloc(BLOCK_SIZE);if(!ptr[i]) fprintf(stderr,"malloc failed. reason:%s\n",strerror(errno));else{//对分配的内存进行使用,要不然可能不会真的进行分配*ptr[i] = '\0';*(ptr[i] + BLOCK_SIZE - 1) = '\0';}}for(i = 0; i < TEST_COUNT ; i++){if(ptr[i]) free(ptr[i]);}}}return 0;
}
运行时间效果:
⭐弊端二
频繁的内存进行申请释放,会增加系统内存的碎片,降低内存的使用效率。
产生的根源是:
1.内存分配必须起始于可被 4、8 或 16 整除(视处理器体系结构而定)的地址
2.MMU的分页机制的限制
内部碎片就是我内存分配给了你,但是呢,其实你用不上
①malloc 是 C 语言中常用的动态内存分配函数,通过 malloc 分配内存时,需要指定所需的内存大小。由于内存分配的原理,当请求的内存大小小于所分配的内存块大小时,就会产生内部碎片。
②具体地说,malloc 会将所需内存大小向上取整到最接近它的 2 的幂次方。例如,如果请求分配 10 字节的内存,由于 2^4 = 16 大于 10,malloc 会分配一个 16 字节的内存块。在这种情况下,由于内存块大小为 16 字节,而所需的内存大小只有 10 字节,就会造成 6 字节的内部碎片。
③如果 malloc 频繁调用并分配小块内存,就会产生大量的内部碎片,从而导致内存浪费。为了减少内部碎片的发生,可以使用内存池技术或自行实现内存分配算法,以更好地管理内存并最小化内存碎片的数量。
⭐弊端三
没有垃圾回收机制,有时候会导致内存泄漏,这里要注意的是,不止是频繁malloc内存然后没有释放会导致内存泄漏,`文件句柄的频繁申请,但是最后都没有close掉它这样也是会造成内存泄漏哟。内存泄漏(Memory Leak)
指的是在程序运行过程中,由于未正确释放动态分配的内存而导致内存空间一直被占用,最终导致系统可用内存逐渐减少,甚至耗尽系统内存的现象。
⭐弊端四
内存分配与释放的逻辑在程序中相隔较远时,降低程序的稳定性。 这个感触就非常深了,有时候自己malloc了一个数组,然后在使用的过程中将指针进行的偏移(比如++操作),导致在最后free内存的时候发生错误,原因就是指针发生的偏移,释放内存这个操作产生了错误。🚀解决方法
⭐内存管理工具选择
⭐内存池技术
在真正使用内存之前,先申请分配一定数量的、大小相等(一般情况下)的内存块留作备用
。当有新的内存需求时,就从内存池中分出一部分内存块,若内存块不够再继续申请新的内存,统一
对程序所使用的内存进行统一的分配和回收。这样做的一个显著优点是,这样分配的小内存就不会东一块西一块而是从大内存块中分出小块内存,让结构更加的紧凑,也不用多次进行系统调用,使得内存分配效率得到很大的提升。
内存池是怎么解决上面所述的弊端的呢?