iis服务器助手广告广告
返回顶部
首页 > 资讯 > 精选 >C标准库堆内存函数的示例分析
  • 719
分享到

C标准库堆内存函数的示例分析

2023-06-15 09:06:20 719人浏览 泡泡鱼
摘要

这篇文章主要为大家展示了“C标准库堆内存函数的示例分析”,内容简而易懂,条理清晰,希望能够帮助大家解决疑惑,下面让小编带领大家一起研究并学习一下“C标准库堆内存函数的示例分析”这篇文章吧。概述C标准库堆内存函数有4个:malloc、free

这篇文章主要为大家展示了“C标准库堆内存函数的示例分析”,内容简而易懂,条理清晰,希望能够帮助大家解决疑惑,下面让小编带领大家一起研究并学习一下“C标准库堆内存函数的示例分析”这篇文章吧。

概述

C标准库堆内存函数有4个:malloc、free、calloc、realloc,其函数声明放在了#include <stdlib.h>中,主要用来申请和释放堆内存。

堆内存的申请和释放(wiki,chs),需要发起系统调用,会带来昂贵的上下文切换(用户态切换到内核态),十分耗时。另外,这些过程可能是带的,难以并行化。

对于操作系统而言,内存管理的基本单位是页(通常为4K),而不是需要4 Bytes时,就给你分配4 Bytes,释放4 Bytes时,就给你释放4 Bytes。

因此,为了提升效率,操作系统会调用系统apiwindows上是VirtualAlloc、VirtualFree,其他平台是mmap、munmap)来实现一个Ansi C内存分配器(工作在用户态),供C标准库堆内存函数来使用。

C标准库堆内存函数的示例分析

不同操作系统Ansi C内存分配器实现方案有所不同

  • windows:MSVCRT.DLL中使用NT heap实现

  • linux:glibc中使用ptmalloc实现

  • Android:使用jemalloc实现

内存碎片与碎片整理

(1)内存碎片(fragmentation):即空闲内存不能被利用。分为外部碎片(在分配单元间的未使用的内存);内部碎片(在分配单元中未使用的内存)

C标准库堆内存函数的示例分析

(2)内存碎片的罪魁祸首就是小块内存的频繁分配

(3)内存碎片无法避免,只能通过内存分配器算法来减少,例如:接近大小的内存就近分配,释放时能合并就合并,从而减少碎片

(4)上面讲的内存碎片指的是虚拟内存碎片,OS是不管的,OS只管物理内存。

(5)平时我们说的内存碎片整理(defragment)或内存紧缩(memory compaction),是指OS对物理内存进行的碎片整理,把分开小的物理内存页移动在一起形成一个大的整块。

OS整理完物理内存后,会用新的物理内存地址来更新虚拟内存与物理内存映射表,这些对于上层逻辑都是透明的。

虚拟内存是不能进行碎片整理的,主要原因是碎片整理会移动内存,上层逻辑的指针地址确还是指向老的地址,这会导致致命错误。

内存分配器的好坏标准

(1)分配和释放的效率

(2)内存分配器的利用率。包括以下几个方面:

① 内存对齐导致的不可使用的内存碎片(内部碎片)

② 内存碎片太严重,使得分配大块内存时,找不到空闲块,最后导致内存分配失败(外部碎片)

③ 内存页始终有被使用,导致分配器无法及时释放该页的内存占用,使得整个内存分配器的内存占用被撑得很大,缩不回去

void* malloc( size_t size )

形参size为要求分配的字节数。如果函数执行成功,malloc返回获得内存空间的首地址;如果函数执行失败,那么返回值为NULL。

由于 malloc函数值的类型为void型指针,因此,可以将其值类型转换后赋给任意类型指针,这样就可以通过操作该类型指针来操作从堆上获得的内存空间。

需要注意的是,malloc函数分配得到的内存空间是未初始化的。可通过调用memset来将其初始化为全0。

int* p = (int *) malloc(sizeof(int)*100); if (p == NULL){    printf("Can't get memory!\n");} memset(p, 0, sizeof(int)*100);

void free( void* ptr )

从堆上获得的内存,在程序结束之前,系统不会将其自动释放,需要程序员来自己管理,防止出现内存泄露。

free(p);p = NULL;

void* calloc( size_t num, size_t size )

calloc函数的功能与malloc函数的功能相似,都是从堆分配内存。

函数返回值为void*。如果执行成功,从堆上获得size * num大小的堆内存,并返回该内存块的首地址。如果执行失败,函数返回NULL。

与malloc函数不同的是,calloc函数得到的内存块会被初始化为全0。由于提供了2个参数,比较适合为数组申请空间,可以将size设置为数组元素的空间长度,将num设置为数组的容量。

int* p = (int *) calloc(100,  sizeof(int)); if (p == NULL){    printf("Can't get memory!\n");}

void *realloc( void *ptr, size_t new_size )

为ptr重新分配大小为size的一块内存空间。下面是这个函数的工作流程:

① 如果ptr为NULL,则函数相当于malloc(new_size),试着分配一块大小为new_size的内存,如果成功将地址返回,否则返回NULL。

② 如果ptr不为NULL,查看ptr是不是在堆中,如果不是的话会抛出realloc invalid pointer异常。如果ptr在堆中,则查看new_size大小。

(a)如果new_size大小为0,则相当于free(ptr),将ptr指向的内存空间释放掉,返回NULL。

(b)如果new_size小于原大小,只有new_size大小的数据会保存,后面地址的数据可能会丢失;

(c)如果new_size等于原大小,什么都没有做;

(d)如果new_size大于原大小,则查看ptr指向的位置还有没有足够的连续内存空间,如果有的话,分配更多的空间,返回的地址和ptr相同;

如果没有的话,在更大的空间内查找,如果找到new_size大小的空间,将旧的内容拷贝到新的内存中,把旧的内存释放掉,则返回新地址,否则返回NULL。

int* p = (int*)malloc(sizeof(int));*p = 3;printf("p=%p\n", p);  // p=0000020B2966E310printf("*p=%d\n", *p); // *p=3p = (int*)realloc(p, sizeof(int));  // 什么也不做printf("p=%p\n", p);  // p=0000020B2966E310printf("*p=%d\n", *p); // *p=3p = (int*)realloc(p, 1024 * sizeof(int)); // 创建4KB的内存块  注:4KB为一个页面的大小printf("p=%p\n", p); // p=0000020B29673A50  注:由于不能在原来地址上扩容,会将原来地址内存释放,并在新地址申请内存块printf("*p=%d\n", *p); // *p=3realloc(p, 0);  // 相当于free(p)p = NULL;

以上是“C标准库堆内存函数的示例分析”这篇文章的所有内容,感谢各位的阅读!相信大家都有了一定的了解,希望分享的内容对大家有所帮助,如果还想学习更多知识,欢迎关注编程网精选频道!

--结束END--

本文标题: C标准库堆内存函数的示例分析

本文链接: https://www.lsjlt.com/news/279344.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

本篇文章演示代码以及资料文档资料下载

下载Word文档到电脑,方便收藏和打印~

下载Word文档
猜你喜欢
  • C标准库堆内存函数的示例分析
    这篇文章主要为大家展示了“C标准库堆内存函数的示例分析”,内容简而易懂,条理清晰,希望能够帮助大家解决疑惑,下面让小编带领大家一起研究并学习一下“C标准库堆内存函数的示例分析”这篇文章吧。概述C标准库堆内存函数有4个:malloc、free...
    99+
    2023-06-15
  • 详解C标准库堆内存函数
    目录概述不同操作系统Ansi C内存分配器实现方案有所不同内存碎片与碎片整理内存分配器的好坏标准void* malloc( size_t size )void free( void*...
    99+
    2024-04-02
  • Java堆栈内存、堆外内存、零拷贝的示例分析
    这篇文章将为大家详细讲解有关Java堆栈内存、堆外内存、零拷贝的示例分析,小编觉得挺实用的,因此分享给大家做个参考,希望大家阅读完这篇文章后可以有所收获。一、堆栈内存堆栈内存,顾名思义,指的是堆内存以及栈内存,其中,堆内存是由Java GC...
    99+
    2023-06-15
  • Node中堆内存分配的示例分析
    这篇文章将为大家详细讲解有关Node中堆内存分配的示例分析,小编觉得挺实用的,因此分享给大家做个参考,希望大家阅读完这篇文章后可以有所收获。V8 垃圾回收简介首先,简单介绍一下V8垃圾回收器。内存的存储分配...
    99+
    2024-04-02
  • JavaScript中标准库的示例分析
    这篇文章将为大家详细讲解有关JavaScript中标准库的示例分析,小编觉得挺实用的,因此分享给大家做个参考,希望大家阅读完这篇文章后可以有所收获。1.什么是标准库(Standard Library)标准库...
    99+
    2024-04-02
  • Golang标准库syscall的示例分析
    小编给大家分享一下Golang标准库syscall的示例分析,相信大部分人都还不怎么了解,因此分享这篇文章给大家参考一下,希望大家阅读完这篇文章后大有收获,下面让我们一起去了解一下吧!一、什么是系统调用In computing, a sys...
    99+
    2023-06-15
  • Redis内存数据库示例分析
    目录redies dict字典Redis的DB实现具体的实现器Redis持久化Aofredies dict字典 这是 Redis 最底层的结构,比如 1个DB 下面有 16个Dict...
    99+
    2022-12-19
    Redis内存数据库 Redis数据库
  • Redis内存数据库分片的示例分析
    这篇文章将为大家详细讲解有关Redis内存数据库分片的示例分析,文章内容质量较高,因此小编分享给大家做个参考,希望大家阅读完这篇文章后对相关知识有一定的了解。 软件下载地址 ·  &...
    99+
    2024-04-02
  • C/C++内存管理的示例分析
    这篇文章主要介绍了C/C++内存管理的示例分析,具有一定借鉴价值,感兴趣的朋友可以参考下,希望大家阅读完这篇文章之后大有收获,下面让小编带着大家一起了解一下。C/C++赋予程序员管理内存的自由,是C/C++语言特色,虽然这引入了复杂度和危险...
    99+
    2023-06-15
  • C语言中库函数的示例分析
    这篇文章主要为大家展示了“C语言中库函数的示例分析”,内容简而易懂,条理清晰,希望能够帮助大家解决疑惑,下面让小编带领大家一起研究并学习一下“C语言中库函数的示例分析”这篇文章吧。1 返回整数的getchar函数代码:#include<...
    99+
    2023-06-29
  • Python标准库的强大功能的示例分析
    Python标准库的强大功能的示例分析,针对这个问题,这篇文章详细介绍了相对应的分析和解答,希望可以帮助更多想解决这个问题的小伙伴找到更简单易行的方法。Python标准库是十分庞大的,其中也有一些质量比较高的库,例如,wXPython、Py...
    99+
    2023-06-17
  • C++中内存管理的示例分析
    这篇文章将为大家详细讲解有关C++中内存管理的示例分析,小编觉得挺实用的,因此分享给大家做个参考,希望大家阅读完这篇文章后可以有所收获。概述内存管理的原理庞大而复杂,然而这些都被操作系统进行了封装,并对外预留了API,这些api被c++调用...
    99+
    2023-06-25
  • python内置函数的示例分析
    这期内容当中小编将会给大家带来有关python内置函数的示例分析,文章内容丰富且以专业的角度为大家分析和叙述,阅读完这篇文章希望大家可以有所收获。range函数能够生成一个指定的数字序列使用案例:'''range(s...
    99+
    2023-06-22
  • Node.js api中POSIX标准的示例分析
    这篇文章主要介绍Node.js api中POSIX标准的示例分析,文中介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们一定要看完!如果你用过 Node.js 的 api,会不会觉得奇怪,为什么 api ...
    99+
    2024-04-02
  • Kotlin标准库函数使用分析及介绍
    目录1.apply 函数2.let 函数3.run函数4.with 函数5.also6.takeIf7.takeUnless1.apply 函数 apply函数可以看做是一个配置函数...
    99+
    2024-04-02
  • 内存型数据库Redis持久化的示例分析
    这篇文章主要为大家展示了“内存型数据库Redis持久化的示例分析”,内容简而易懂,条理清晰,希望能够帮助大家解决疑惑,下面让小编带领大家一起研究并学习一下“内存型数据库Redis持久化的示例分析”这篇文章吧...
    99+
    2024-04-02
  • C++函数栈帧的示例分析
    这篇文章将为大家详细讲解有关C++函数栈帧的示例分析,小编觉得挺实用的,因此分享给大家做个参考,希望大家阅读完这篇文章后可以有所收获。一、什么是函数栈帧每一次函数调用都是一个过程,为函数开辟栈空间,用于本次函数调用中临时变量的保存、现场保护...
    99+
    2023-06-20
  • C++程序内存栈区与堆区模型案例分析
    目录栈区:栈区代码演示:堆区:堆区代码演示:new操作符:new操作符代码演示:栈区: 由编译器自动分配释放,存放函数的参数值,局部变量等(由编译器管理其“生死&rdqu...
    99+
    2024-04-02
  • MySQL中存储函数的示例分析
    这篇文章将为大家详细讲解有关MySQL中存储函数的示例分析,小编觉得挺实用的,因此分享给大家做个参考,希望大家阅读完这篇文章后可以有所收获。存储函数什么是存储函数: 封装一段sql代码,完成一种特定的功能,...
    99+
    2024-04-02
  • Python数据分析之堆叠数组函数示例总结
    目录numpy 堆叠数组ravel() 函数stack() 函数vstack()函数hstack()函数concatenate() 函数numpy 堆叠数组 在做图像和 nlp 的...
    99+
    2023-02-23
    Python堆叠数组函数 Python 数据分析
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作