欢迎光临
我们一直在努力

C语言入门指南:从零到精通

十四、动态内存管理

1.动态内存分配

        动态内存分配指在程序运行时根据需要分配和释放内存的过程,与静态内存分配不同。允许程序更灵活地管理内存资源,适用于不确定数据规模或需要动态调整内存的场景。

2.malloc和free

        (一)malloc:分配指定字节数的未初始化内存块。

语法形式:

        void* malloc(size_t size);

        *若开辟成功,则返回一个指向开辟好空间的指针;若开辟失败,则返回一个NULL指针。
        *返回值一定要做检查。
        *返回值的类型是void*,malloc函数并不知道开辟空间的类型,具体要使用者自己决定。
        *若size为0,具体实现由编译器决定。
        *使用时需要包含头文件<stdlib.h>。

        (二)free:释放动态分配的内存。

语法形式:

        void free(void* ptr);

        *如果参数ptr指向的空间不是动态开辟的,则free函数的行为是不可预测的。
        *如果参数ptr是NULL指针,则函数什么都不做。
        *ptr使用结束后将其赋值NULL。
        *使用时需要包含头文件<stdlib.h>。

3.calloc和realloc

        (一)calloc:分配并初始化内存为零。

语法形式:

        void* calloc(size_t num,size_t size);

        *calloc函数的功能是为num个大小为size的元素开辟一块空间,并将每个字节初始化为0;
        *与函数malloc的区别就是在返回地址前会初始化。

        (二)realloc:调整已分配内存块的大小。

语法形式:

        void* realloc(void* ptr,size_t size);

        *ptr:指向之前通过malloc,calloc,realloc分配的内存块的指针,如果ptr为NULL,realloc的效果等同于malloc。

        *size:新的内存块大小。如果size为0,ptr不是NULL,realloc的效果等同于free。

        *realloc尝试调整现有内存块的大小。如果当前内存块之后有足够的连续空间,函数会直接扩展内存块并返回原指针。如果没有足够的空间,realloc会分配一个新的内存块,将原数据复制到新的内存块中,并释放旧的内存块。
        *内存分配失败,realloc会返回NULL,但原内存块不会释放。为避免内存泄漏,建议先将返回值赋给一个临时指针比哪里,检查非NULL后在更新原指针。

4.常见的动态内存的错误

        (一)对NULL指针的解引用操作

        注意对动态开辟内存的指针进行检查,若为空指针则不能使用。

        (二)对动态开辟空间的越界访问

        访问时注意开辟空间的大小。

        (三)对非动态开辟空间使用free释放

        free只能释放动态开辟空间。

        (四)使用free释放一块动态开辟内存的一部分

        释放动态开辟空间时检查指针是否是动态空间的起始位置。

        (五)对同一块动态内存多次释放

        同一块内存多次释放会引发未定义行为,遵循“谁分配谁释放”原则。(malloc和free成对出现)

        (六)动态开辟内存忘记释放(内存泄漏)

        释放内存后应将指针置为NULL,动态分配内存后要检查返回值是否是NULL。

*对于malloc/calloc/realloc申请的内存,可以使用free释放。如果没有使用free释放,当程序运行结束时,操作系统也会回收。

5.柔性数组

        (一)柔性数组是C99标准引入的一种特殊数组,定义在结构体的最后一个成员位置,且不指定数组长度。

语法形式:

        struct example

        {

                int length;

                char data[];//柔性数组

        };

        *结构中的柔性数组成员前面必须至少有一个其他成员。
        *sizeof返回的结构大小不包括柔性数组的内存。
        *包含柔性数组的结构用malloc()函数进行内存的动态分配,并且分配的内存应该大于结构的大小,以适应柔性数组的预期大小。

        (二)柔性数组的优势:结构体和数组内粗连续,提升缓存命中率。仅需一次malloc/free操作,降低内存管理复杂度。

6.总结C/C++中程序内存区域划分

        在C/C++中,程序运行时内存通常划分为以下几个主要区域:

        (一)内核空间

        操作系统内核运行的内存区域。

        (二)栈

        栈内存由编译器自动分配和释放,存储局部变量,函数参数以及返回地址。速度快但容量有限,栈空间从高地址向低地址增长。

        (三)内存映射段

        进程虚拟地址空间的一部分,用于将文件或设备直接映射到内存中。

        (四)堆

        由程序员自己申请,通过malloc、calloc、realloc分配和free释放。堆空间从低地址向高地址动态增长,容量受系统剩余内存限制,分配速度慢但是比较灵活。若程序员不释放,程序结束时可能由OS回收。

        (五)数据段(静态区)

        存储全局变量、静态变量。程序运行时分配,结束后释放。未初始化的变量会自动初始化为0.

        (六)代码段

         存储函数体(类成员函数和全局函数)的二进制代码。

赞(0)
未经允许不得转载:171主机测评 » C语言入门指南:从零到精通
分享到: 更多 (0)

评论 抢沙发

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址