在这一次中来学习一下C语言的内存布局,了解它之后就可以解释为啥在用malloc()申请的内存之后需要用memset()来对内存进行一下初始化了,首先来了解一下物理内存与虚拟内存:

  • 物理内存:通过物理内存条获得的内存空间。
  • 虚拟内存:它是一种内存管理技术,能够均处一部分硬盘空间充当内存使用。

而在C当中的内存布局如下:

其中最顶部的是内核空间:

除这个内核空间之外的则是用户进程的内存空间:

下面看一下有哪些内容,首先是栈区:

接着是内存映射段:

接着就是堆区了:

接着再就是数据段:

最后一个则是文本段:

咱们基于上面的来画一个简化版本:

其中“预留区”是程序看不见的区域,系统预留滴,对于程序而言是木有啥用的~~

这里来对堆内存地址由低往高进行说明:在堆区申请内存是调用了glibc(C的标准库、运行库,类似于java的JDK)提供的malloc方法,而它的底层是由Linux的brk和mmap两种方式来实现的,而其中:brk申请内存的方式是将内存指针(假设为_edata)往高地址堆,目前_edata指向堆内存的起始位置 :

假如申请10K的内存,此时就会将_edata由低地址往上推10K的大小,如下:

如果再申请一个10K,同样的往上再推10K,如下:

那如果A被释放掉了,会发生什么情况呢?此时的_edata并不会回退,而是A这个10K的区域成了内存碎片了,如下:

那此时如果再申请一个10K的内存,发现A这个空间刚好满足则会重用它,_edata并不会往上再去开辟新内存空间,那假如申请的内存大于10K,比如11K,此时A这个区域内存满足不了要申请的11K大小,所以还是会往上推11K大小的内存,如下:

那brk方式申请的内存就永远不会收缩么,其实不是这样的,像这种场景就会:此时C被释放了,内存就会收缩了,如下:

而对于mmap申请内存的方式为:找一块满足大小的内存既可,而不会像brk方式往上今次推指针,所以它的内存随时都可以被释放的,那什么时候用brk,什么时候用mmap呢?其实是要申请的堆内存小于128k则用brk方式申请,否则用mmap申请,注意:此128K是个阈值,是可以人为配置的。

好,明白了上面的之后,回到咱们开篇所指出的问题:为啥在malloc动态申请内存之后,需要用memset手动再去给内存进行一个初始化?因为brk方式有可能会存在复用之前申请过的内存,如果不初始化有可能该内存是之前申请过的,这样就会造成一些数据的混乱。

那对于malloc底层为啥不全采用mmap方式来实现呢?因为mmap效率明显不如brk推指针的方式,所以就存在于两种方式来实现了。

另外对于数组而言其实是一段连续的内存地址,如下:

头文件基础知识:

我们知道对于C、C++的代码通常是有.h头文件和.c&.cpp的源文件的,如下:

那么在.h头文件中能否有具体实现呢?答案是肯定的,下面来试验一下:

但是!!平常一般是不会这么用的,这里只是作为一个话题在探讨。

另外对于要使用指定头文件是需要用include来将其包含进来的,类似于java中的import,如下:

但是!跟java中的import是有区别的,在java中是不能够传递import的,怎么理解,看下面java代码:

而ArrayList里面是import了它了:

那如果我们在main中也想用Consumer这个类的话,还需要再导一遍,如下:

也就是说:虽然ArrayList已经import过了Consumer,而我们在main中也已经import了ArrayList,但是Consumer并不会被传递到main方法中,使用时是需要再次导入的,但是!C中是可以传递include的,下面用代码来说明一下:

然后在main.h中去include我们新建的这个头文件:

那我们在main.c中能否去调用a头文件中声明的test3()函数呢,当然能:

那思考一下为啥C、C++要分一个头文件和源文件,而不像Java只有一个源文件呢?其实.h就是将行为给暴露,其具体实现不暴露,当然如果想暴露具体实现那可以在.h中去用具体的方法来暴露,如:

而通常的只定义了函数的声明,如:

这样当别人想使用该函数时只需要include头文件既可,具体的实现细节则不会暴露给调用者。

CMake简单介绍:

由于咱们工程是采用CMakde来进行构建的,当然未来会细学它的,这里只是说明一下当新建了一个文件时记得在CMake中加入一下,具体如下:

ndk学习之C语言基础复习----虚拟内存布局与malloc申请的更多相关文章

  1. ndk学习之C语言基础复习----基本数据类型、数组

    关于NDK这个分类在N年前就已经创建了,但是一直木有系统的记录其学习过程,当然也没真正学会NDK的技术真谛,所以一直也是自己的一个遗憾,而如今对于Android程序员的要求也是越来越高,对于NDK也是 ...

  2. ndk学习之c++语言基础复习----C++容器、类型转换、异常与文件流操作

    继续来复习C++,比较枯燥,但是这是扎实掌握NDK开发的必经之路,不容小觑. 容器: 容器,就是用来存放东西的盒子. 常用的数据结构包括:数组array, 链表list, 树tree, 栈stack, ...

  3. ndk学习之c++语言基础复习----面向对象编程

    关于面向对象编程对于一个java程序员那是再熟悉不过了,不过对于C++而言相对java还是有很多不同点的,所以全面复习一下. 类 C++ 在 C 语言的基础上增加了面向对象编程,C++ 支持面向对象程 ...

  4. ndk学习之c++语言基础复习----C++线程与智能指针

    线程 线程,有时被称为轻量进程,是程序执行的最小单元. C++11线程: 我们知道平常谈C++线程相关的东东基本都是基于之后要学习的posix相关的,其实在C++11有自己新式创建线程的方法,所以先来 ...

  5. ndk学习之C语言基础复习----结构体、共用体与C++开端

    自己实现sprintf功能: 关于C中的系统函数sprintf在上次[https://www.cnblogs.com/webor2006/p/7545627.html]学习中已经用到过了,这里再来回顾 ...

  6. ndk学习之C语言基础复习----指针、函数、预处理器

    指针: 指针乃C.C++的灵魂之所在,所以有必要好好的复习复习.什么是指针?一句话来概括:“指针是一个变量,它的值是一个地址.”,其中指针变量的声明有如下三种形式: 其中第一种是被推荐的写法. 其中还 ...

  7. MySQL学习笔记_8_SQL语言基础复习

    SQL语言基础复习 一.概述 SQL语句注释方式 1)以"#"开头直到行尾的所有内容都是注释 2)以"--"(--后还有一个空格)开头直到行尾的所有内容都是注释 ...

  8. Java学习笔记:语言基础

    Java学习笔记:语言基础 2014-1-31   最近开始学习Java,目的倒不在于想深入的掌握Java开发,而是想了解Java的基本语法,可以阅读Java源代码,从而拓展一些知识面.同时为学习An ...

  9. C语言基础复习总结

    C语言基础复习总结 大一学的C++,不过后来一直没用,大多还给老师了,最近看传智李明杰老师的ios课程的C语言入门部分,用了一周,每晚上看大概两小时左右,效果真是顶一学期的课,也许是因为有开发经验吧, ...

随机推荐

  1. Selenium ? 也要学...!

    一.selenium 简介 Selenium是ThroughtWorks公司一个强大的开源Web功能测试工具系列,包括Selenium-IDE.Selenium-RC.Selenium-Webdriv ...

  2. 【转】Linux用Nasm巧汇编

    看到一篇总结nasm的使用,解决了我的一点问题,下面是原文链接 原文链接:https://blog.csdn.net/zdwzzu2006/article/details/3990502

  3. eNSP——利用三层交换机实现VLAN间路由

    原理: VLAN将一个物理的LAN在逻辑上划分成多个广播域.VLAN内的主机间可以直接通信,而VLAN间不能直接互通. 在现实网络中,经常会遇到需要跨VLAN相互访问的情况,工程师通常会选择一些方法来 ...

  4. v-bind 绑定属性

    与mustache相区别,他是对内容(content内部)进行修改的.v-bind的语法糖写法是   : v-bind 动态绑定class属性:v-bind:class="对象名" ...

  5. mui 打包发布ios 测试

    1.首先在Hbuilder新建一个app项目,把你的代码放进来 2.在manifest.json里设置你想要的一切,图标,应用名,描述,入口页面等等等,然后再配置好你程序里需要用到的模块权限,按需配置 ...

  6. sqlserver2005版本的mdf文件,还没有log文件,

    https://www.cnblogs.com/wanglg/p/3740129.html  来自此文 仅做备忘  感谢提供信息让我处理好此问题 sqlserver mdf向上兼容附加数据库(无法打开 ...

  7. Paypal、Stripe、Braintree,跨境电商金流第三方支付该用哪家?

    在台湾做跨境电子商务生意,电商网站的金流肯定是一个最大的麻烦,Paypal或是Stripe和Braintree则是国际上大家最常用的金流整合第三方支付服务商.这些金流服务大幅简化网站付费过程,都让消费 ...

  8. Linux精简版系统安装网络配置问题解决

    参考文档:https://www.jianshu.com/p/7579a2ad1c92 通过链接中的文档配置linux系统的时候,在执行命令yum install net-tools的这里提示错误,是 ...

  9. STM32的I2C通讯过程

    使用I2C外设通讯时,在通讯的不同阶段它会对“状态寄存器(SR1 及SR2)”的不同数据位写入参数,通过读取这些寄存器标志来了解通讯状态. 1.主发送器 可使用STM32标准库函数来直接检测这些事件的 ...

  10. Hibernate一对多自关联、多对多关联

    今天分享hibernate框架的两个关联关系    多对多关系注意事项 一定要定义一个主控方 多对多删除 主控方直接删除 被控方先通过主控方解除多对多关系,再删除被控方 禁用级联删除 关联关系编辑,不 ...