C语言分配内存时间,用C语言分配内存

080053208.png

C程序的内存结构

C语言之所以复杂是因为它的内存模型是必不可少的. 与某些高级语言不同,使用对象时只需要使用new进行创建. 之后,您无需担心所有事情. 对于C语言,与内存相关的所有事物都需要熟悉,否则,很长一段时间以来,它总是会步履维艰. 下图是C程序的典型存储器结构. 当然,有一个重要前提. 这样的布局在虚拟内存中:

2ad0593ca049419eb60e7fe0c717650c.png

关于虚拟内存内核维护一个页表(page table),该页表用于表示虚拟内存与物理内存地址或磁盘(交换区域)之间的映射关系. 并非所有虚拟地址都需要映射到物理内存上,否则,无论计算机的存储库有多大,如果再打开几个进程,内存将被消耗. 当您需要使用内存时,请应用到操作系统. 如果请求合法,则内核将条目添加到页表中,以在虚拟地址和物理地址之间建立映射. 同样,当需要释放时,将释放映射并返回资源.

关于虚拟内存的优势,“ Linux编程接口”给出了一个相对完整的答案:

进程与内核之间是相互隔离的,因此一个进程无法读取或修改另一个进程或内核的内存. 通过使每个进程的页表条目指向RAM(或交换区域)中物理页的不同集,可以实现这一点.

在适当情况下,两个或多个进程可以共享内存. 内核通过使不同进程中的页表条目引用RAM的相同页来实现这一点. 内存共享发生在两种常见情况下:

–执行同一程序的多个进程可以共享该程序代码的单个(只读)副本. 当多个程序执行相同的程序文件(或加载相同的共享库)时,会隐式执行这种共享.

23220836-4fce9f32fcbad4826e484ff6f3c9c3.jpg

–进程可以使用shmget()和mmap()系统调用来显式请求与其他进程共享内存区域. 这是出于进程间通信的目的.

便于实施存储器保护方案;也就是说,可以标记页表项,以指示相应页的内容是可读,可写,可执行或这些保护的某种组合. 在多个进程共享RAM页的情况下,可以指定每个进程在内存上具有不同的保护例如,一个进程可能具有对页面的只读访问权限,而另一个进程具有对读写的访问权限.

程序员和诸如编译器和链接器之类的工具无需关心RAM中程序的物理布局.

由于仅一部分程序需要驻留在内存中,因此程序加载和运行更快. 此外,一个进程的内存占用量(即虚拟大小)可能会超过RAM的容量.

虚拟内存管理的最后一个优势是,由于每个进程都使用较少的RAM,因此可以同时在RAM中保留更多的进程. 这通常可以提高CPU利用率,因为它增加了在任何时候,至少有一个CPU可以执行的进程的可能性.

本文主要讨论堆区域中内存分配的一些细节.

使用系统调用

通常,我们将堆的当前边界称为“程序中断”. 在堆区域中分配内存是将程序中断移到更高地址的过程. UNIX系统中的两个系统调用与此程序中断关系最密切:

18b65dd470b4de0c667c779488f19ca4.png

int brk(void * addr);

无效* sbrk(intptr_t增量);

sbrk()用于通过将程序中断移动增量长度来增加和释放内存. 由于虚拟内存是按页分配的,因此增量值不是实际分配的结果. 只要它不是页面大小的整数倍,就会多提供一个页面,而不是四舍五入,除非内存不足,否则总会提供更多页面. sbrk(0)显示当前程序中断. 当尝试访问除程序中断以外的存储器时,将生成SIGSEV信号并发生段故障. brk()和sbrk()的用法类似.

1 intmain()2 {3 int* p = sbrk(100);4 *(p+1023) =4;5 printf("**\n");6 *(p+1024) =4;7 }

适用于内核的一段代码,用于100个字节的内存. 实际上,它映射一个内存页面. 第4行访问内存页面的最后4个字节,并将其重写. 第6行访问映射关系之外的内存. 非法,该程序的运行结果如下:

$ a.out

**

分段错误

c1a5e7b0fc0646caf4fef91dff136c2d.png

使用brk()/ sbrk()释放内存时,映射关系可能不会立即释放. 当程序中断掉落超过一页时,可以将请求的物理内存返回给内核. 当然,释放后对该内存的所有操作都是不确定的,就像玩火一样. 同时,应该注意的是c语言内存分配对应,程序中断的移动不能移到堆区域之外,例如bss区域,数据区域等,这种行为基本上是致命的行为.

使用C标准库函数

malloc()/ free()绝对是C语言中使用最广泛的函数之一. 与brk()/ sbrk()相比,另一个接口更简单,并且还允许释放内存. (当程序中断向下移动以释放内存时,Brk()/ sbrk()无法自由释放,并且顶部的“ innocent”元素也将被释放. )例如,这种情况(此处的内存映射为已发布): <

8e8faaa97456062218faefe23c2e4096.gif

free()释放没有这样的“坑”,因为自由释放内存不一定会导致程序中断. 如果在free()释放的内存上方(在高内存地址处)仍然有可用内存,则程序中断将不会移动,因此不会释放映射关系,这意味着该内存尚未返回到内核. 相反,它将作为免费内存移交给免费维护. 当下一个malloc应用程序执行时,它将将该内存(如果足够的话)返回给malloc. 那么,free如何知道空闲内存的大小?这是因为malloc返回的内存具有特殊的结构:

ab8e9d4dc88d3058f0305bd82251a0d7.png

此存储器的大小记录在该存储器的前面. 回收该内存时,将记录其长度和地址. 再次使用malloc时,它将比较可用内存列表与满足要求的内存,并将其移交给程序以供“第二次使用”(或N次使用). 当然,可用内存列表的使用取决于具体情况:

1. 如果可用内存大于malloc应用程序,则将其一部分剪切并返回给malloc,其余部分将被视为下一个malloc的可用内存.

26afef2dbce9bbc088c69fecbce45aae.gif

2. 如果在malloc期间没有合适的可用内存,则程序中断将照常移动,并且可能会应用新的内存(在上一次映射期间可能会有多余的内存,因此不需要重新映射).

了解了这些基本实现后,我们发现malloc()和free()是更危险的函数. 使用请求的内存时要特别小心,尤其是边界条件,否则结果可能是灾难性的. 例如,在这种情况下,在使用分配的内存之后,仅越过一个字节,而这个字节记录了另一内存的长度. 释放此内存后,free保持错误的长度. 下次有内存请求时,该内存将移交给malloc,这样就会出现“灾难”.

其余的内存分配功能

void * calloc(size_t nmemb,size_t size);

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

calloc()与malloc类似,它分配大小为nmemb的对象,但与malloc不同: calloc会将分配的内存初始化为0.

realloc()的名称意为“重新分配”,用于调整分配的内存ptr的大小,如果ptr之后的内存不足,它将申请一个新区域,原样复制原始内存,新建增加的内存未初始化. 因此,返回的结果可能与ptr不同,实际上,在某些情况下它并不相同. 因此,重新分配效率不够高. 建议不要将其用作最后的手段.

无效* alloca(size_t大小);

该功能是在堆栈上分配内存. 手册中对此进行了描述:

alloca()函数在调用者的堆栈帧中分配大小字节的空间. 当调用alloca()的函数返回其调用者时,此临时空间将自动释放.

在堆栈上分配内存的方案并不多. 例如,执行非本地跳转时,setjmp和longjmp需要使用分配的内存. 您应该考虑使用alloca,因为他申请的内存将自动释放c语言内存分配对应,所以当longjmp反弹时不会出现内存泄漏. 偶尔使用此功能有利于身心健康.

本文来自电脑杂谈,转载请注明本文网址:

http://www.pc-fly.com/a/jisuanjixue/article-276649-1.html

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值