c语言之动态内存规划实践

 更新时间:2026年07月14日 10:50:04   作者:知无不研  
还在为C语言动态内存管理头疼?本文深入讲解堆区内存申请、释放和重新分配,涵盖malloc、free、realloc的用法与常见陷阱,如空悬指针、二次释放和内存泄漏,学会这些,避免程序崩溃,提升代码健壮性

当程序被执行的时候要给它两个资源,一个是CPU资源,一个是内存资源,内存分为四个区

从堆区申请内存叫动态内存管理

栈区是函数调用时为函数中的局部变量分配空间,调用完后销毁,由系统管理。

在栈区分配的空间叫做栈帧

可以在这里面重新定义栈的大小,按照字节给的

windows里面的堆区大小为2g,linux的堆区大小为2.7 2.8g接近三g

动态的含义是:在程序运行的过程中

使用动态内存函数时需要用到malloc.h或者stdlib.h

在堆区动态的申请内存主要有三种方式

这三种方式对应三种函数:

1:size代表字节数,malloc返回无值类型指针

申请成功,返回的是所申请的连续内存空间的首地址

申请失败,返回的是一个空指针

需要指针类型保存它的首地址

它malloc返回的是void型的指针,但是ip是int,所以需要强制转换为int

空类型指针,可以被强转为任何类型指针

在对堆区申请的内存进行释放操作的是free函数:

void free(void*p)

只能释放堆区的空间

申请是把某块空间变成引用状态,释放是把引用状态变成未用状态,说明未用。系统会把free的空间打成d,并说明这块空间可以重新引用,打d的目的是为了消除之前的数据,下个使用者再次使用的时候就不能再次使用上个使用者保存的数据,保障安全性

但是ip自身的值没有改变,ip是空悬指针(没有被声明的内存),所以需要把ip赋值为空指针

free是把ip指针所指的位置还给堆区

free之后ip已经跟该空间没有关系了,但是ip仍然指向该空间,仍然可以赋值所以释放完后,一定要把free置为空。更可怕的是。如果ip用完后没有置为空,那它还指向那片空间,如果有is再申请了动态内存如果还含有那片空间,那么无论是给ip赋值还是free(IP)都会对is造成影响,会改变is的值或者is的空间释放,is指向的空间就莫名其妙的失效了

2:colloc函数

colloc函数将申请的内存空间都初始化成0,这是与malloc的主要区别

malloc是将申请的内存空间都初始化成cdcdcd/随机值

在使用动态内存函数的时候,一定要注意判读申请的内存空间是否成功

if(NULL==ip)exit(1);
//exit就是终止函数 后面是1,就是必终止

c语言是类型为王,ip有自己的类型,所以可以对IP解引用

可以通过ip[0]访问申请的空间,所以ip[0]=12就是把申请的内存的第一个空间给成了12

ip[0]=*(ip+0)

如果释放空间后又释放,那么系统会直接给你报错,一旦释放,一定要置为空

一定不要二次释放,因为该空间有可能被别的指针指上并赋值

对于free函数,在free函数里面,如果free的值为空,那它就直接返回了。

如果指针是null,就会直接返回

不为空才释放空间

在用动态内存函数申请空间时,为了防止使用的空间用完了越界,会有上越界和下越界标记,如果上下越界被修改,那就认为程序在运行的过程中出现了越界的问题,free在使用中也会判断是否越界,上越界以上会有头部标记(报头)(头部标记一共占用了28个字节,有4个字节记录了你要申请的字节数),(里面是fdfdfd)占用的字节数为强转的指针大小

报头里面有两个指针,会把你分配给用户的内存块分配到链表里面去

free在运行的时候会读取头部标记,知道释放的字节数

问题1:malloc在申请的时候有说明申请的内存的大小,那为什么free在释放的时候没有传入释放内存的大小?

free在释放的时候,从上越界向上读取完头部标记,就知道自己要释放多少个字节

也就是说,为了达成malloc和free之间的工作方式,给出了一个协议,在malloc申请字节的时候申请的字节比想要申请的字节数大,大了上越界,下越界,和头部信息这么多字节

free在释放的时候,连同上越界,下越界,标记信息都一同释放

free在释放的时候,向上偏移到头部标记,这样就知道自己该释放多少个字节

那我不需要知道字节数,从头部标记一同释放到下越界不就好了?

上下越界会导致用户用数据覆盖,一同释放到下越界会使得用户数据丢失

释放内存时不能部分释放,要么不释放,要么释放完

内存泄漏是什么?

内存泄漏就是,在内存申请完后没有内存释放,或者用动态内存函数获得申请的空间的地址丢失,一旦丢失,意味着你永远也找不到释放的空间的首地址,这也是内存泄漏,所以,一定不要丢失这个地址

为什么空地址就不能给值?

空地址不能解析,不能读或者写,操作系统对0地址有保护,不让对他进行读写,否则操作系统认为出错

3:realloc函数(很重要)

当你发现之前用 malloc 或 calloc 申请的空间太小(不够用)或者太大(浪费)时,就需要请出 realloc

  • 全称: Re-allocation(重新分配)。
  • 特点: 可以修改已分配内存块的大小。它会保留原内存中的数据(如果新空间变大,新增的部分是未初始化的随机值)。
  • 原地扩容: 如果原内存块后面有足够的空闲空间,它直接“向后”延伸,地址不变。
  • 异地搬迁: 如果原地空间不足,它会在堆上找一块全新的、足够大的空间,把旧数据复制过去,释放旧空间,并返回新地址

重要警告:

由于 realloc 可能会改变内存地址,必须用一个新的指针变量接收返回值,或者直接赋值给原指针(但要确保原指针没丢,通常建议先用临时指针接收,判空后再赋值)。

如果传入的 ptr 是 NULLrealloc 的行为等同于 malloc

总结

以上为个人经验,希望能给大家一个参考,也希望大家多多支持脚本之家。

相关文章

  • 使用代码验证linux子进程与父进程的关系

    使用代码验证linux子进程与父进程的关系

    Linux下父进程可以使用fork 函数创建子进程,但是当父进程先退出后,子进程会不会也退出呢?通过下面这个小实验,我们能够很好的看出来
    2014-02-02
  • C++ 使用new与delete需注意的原则

    C++ 使用new与delete需注意的原则

    这篇文章主要介绍了C++ 使用new与delete需注意的原则,帮助大家更好的理解和学习c++,感兴趣的朋友可以了解下
    2020-08-08
  • c语言可变参数实现示例

    c语言可变参数实现示例

    这篇文章主要介绍了c语言可变参数实现示例,需要的朋友可以参考下
    2014-04-04
  • 一文带你了解C语言中static关键字的3个作用

    一文带你了解C语言中static关键字的3个作用

    static这个关键字是“静态”的意思,在C语言里主要有3个作用。这篇文章主要通过一些简单示例为大家详细讲讲这3个左右,感兴趣的小伙伴可以了解一下
    2023-04-04
  • C++中结构体的类型定义和初始化以及变量引用

    C++中结构体的类型定义和初始化以及变量引用

    这篇文章主要介绍了C++中结构体的类型定义和初始化以及变量引用,是C++入门学习中的基础知识,需要的朋友可以参考下
    2015-09-09
  • C语言字符串替换空格实例详解

    C语言字符串替换空格实例详解

    这篇文章主要为大家详细介绍了C语言字符串替换空格实例,使用数据库,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下,希望能够给你带来帮助
    2022-02-02
  • 深入理解c++模板中的class与typename

    深入理解c++模板中的class与typename

    在c++Template中很多地方都用到了typename与class这两个关键字,而且好像可以替换,是不是这两个关键字完全一样呢?下面这篇文章主要给大家介绍了关于c++模板中class与typename的相关资料,需要的朋友可以参考下。
    2017-07-07
  • C++ auto类型说明符

    C++ auto类型说明符

    在C++11中引入了auto类型说明符,用它就能让编译器替我们去分析表达式所属的类型。当然,auto变量必须有初始值,这样编译器才能推断其类型
    2016-03-03
  • C++中template方法undefined reference to的问题解决

    C++中template方法undefined reference to的问题解决

    Undefined reference to 错误:这类错误是在连接过程中出现的,本文就来介绍一下C++中template方法undefined reference to的问题解决,具有一定的参考价值,感兴趣的可以了解一下
    2024-03-03
  • Qt物联网管理平台之实现数据查询导出打印

    Qt物联网管理平台之实现数据查询导出打印

    这篇文章主要为大家介绍了如何利用Qt编写物联网管理平台中数据查询导出打印的功能,文字的示例代码讲解详细,感兴趣的可以了解一下
    2022-07-07

最新评论