C++源文件从文本到可执行文件经历的过程

references:

一个C++源文件从文本到可执行文件经历的过程


C++源文件从文本到可执行文件经历的过程

gcc程序编译的静态链接和动态链接

保留中间过程文件:a.i, a.s, a.o, a.out

g++ a.cpp -save-temps

1、预处理阶段:

对源代码文件中文件包含关系(头文件)、预编译语句(宏定义)进行分析和替换,成预编译文件。

  • 处理“#include”预编译指令,将文件内容替换到它的位置
  • 展开宏定义
  • #ifndef作用
  • 删除注释
  • 等等

g++ -E a.cpp -o a.i

2、编译阶段

将经过预处理后的预编译文件转换成特定汇编代码,生成汇编文件

g++ a.cpp -S

3、汇编阶段

将编译阶段生成的汇编文件转化成机器码,生成可重定位目标文件

g++ -c a.s -o a.o

4、链接阶段

将多个目标文件及所需要的库连接成最终的可执行文件。链接分为静态链接和动态链接。

  • 静态链接:链接器将需要使用的库函数的一份拷贝加入到可执行文件中。优点是简单,速度快;缺点是空间耗费大,函数更新后就要重新编译链接可执行文件。
  • 动态链接:可执行文件只是包含了文件名,运行时才把他们链接到一起。优点是可执行文件体积小,更新方便;缺点是运行速度慢。

g++ a.o -o a //动态链接

g++ a.o -static -o a //静态链接

include头文件的顺序

如果a.h中定义了b.h中声明的变量并且a.h没有引用b.h,那么引用a.h前要先引用b.h。

当然这是显然的。

include双引号””和尖括号<>的区别

预处理阶段查找头文件的路径不一样。

  1. 双引号:

    编译器从用户工作目录开始,再找系统默认目录。
  2. 尖括号:

    编译器只找系统默认目录。

malloc底层原理

references:

nowcoder


linux-malloc底层实现及原理

Linux内存分配原理

LInux下,小于128K时,用brk;大于128K时用mmap。

注意了,brk和mmap都是分配的虚拟内存而不是物理内存,等第一次访问到分配的内存时,会产生缺页中断,这时内核才会分配物理内存。也就是说,从不访问就不会分配物理内存。

brk调用和mmap调用虚拟内存

references:

内存分配系统调用:brk和mmap


请问malloc的分配为什么是小内存用brk,大内存用mmap,各自有什么好处?

Linux中brk()系统调用,sbrk(),mmap(),malloc(),calloc()的异同

实现虚拟内存到内存的映射

申请内存小于128K的时候,使用brk系统在堆区分配;大于128K的时候,使用mmap在映射区分配。

原因:

brk指针只有一个,分配内存时是把进程堆的最高地址往高地址上推,只有高地址释放后才能释放低地址内存,如果大内存用brk分配会产生内存碎片。

mmap分配内存可以单独释放,但是分配小内存使得缺页中断次数增加,性能下降。

内存泄漏

references:

nowcoder

1、堆内存泄漏:new/malloc之后没有deete/free,申请的内存没有释放。

2、系统资源泄漏:主要指程序使用系统分配的资源比如 Bitmap,handle ,SOCKET等没有使用相应的函数释放掉,导致系统资源的浪费,严重可导致系统效能降低,系统运行不稳定。

如何判断内存泄漏

references:

Q28:如何判断内存泄漏

使用Linux环境下的内存泄漏检查工具Valgrind。

段错误

访问非法内存地址(数组访问越界等),访问只读的内存地址(字符串常量等),栈溢出。

C++ STL 的内存优化

references:

C++ STL中的内存优化

采用两级配置器结构:

一级配置器

申请空间大于128byte,使用一级配置器。包含malloc()、remalloc()、free()等C函数执行实际的内存配置,释放,重新配置等操作。

二级配置器

分配小于128字节内存时,以内存池进行管理。

内存池每次配置一块内存,并维护对应的16个空闲链表(free-list),每个节点分别管理大小为为8,16,24,32,……,120,128的数据块。

向二级配置器申请时,将申请内存扩大到8的倍数,去找空闲链表对应的位置,然后找子链表。子链表不为空,就分配链表头表示的内存,表头指向下一个节点;为空则向内存池申请(一般一次20块),分配到子链表中,再把链表头分配出去。

作用:在STL的第二级配置器中多了一些机制,避免太多小区块造成的内存碎片,小区块造成的不仅仅是内存碎片,同时还有一些额外的负担。区块越小,额外的负担所占的比重越大。

最新文章

  1. Windows10上安装EDEM2.7
  2. python之路:Day02 --- Python基础2
  3. SQL Server日志文件(LDF文件)
  4. javax.mail.MessagingException: 501 Syntax: HELO hostname Linux端异常解决
  5. [Design Pattern] Mediator Pattern 简单案例
  6. hibernate详解
  7. PHP学习笔记9-生成图片
  8. 如何在Git中撤销一切 | 干货
  9. LoadRunner脚本参数化之自动关联和手动关联
  10. Qt中的Q_D宏和d指针
  11. Mysql windows版本的安装
  12. ES6 模块与 CommonJS 模块的差异
  13. 【UML】:类图
  14. tcp socket/ unix socket
  15. BarTender连接不上数据库怎么办
  16. C# 之String以及浅拷贝与深拷贝
  17. 最邻近规则分类KNN算法
  18. select2 使用教程
  19. cmd编译java程序出现:找不到或无法加载主类的原因以及解决办法 以及 给java的main方法传递args参数
  20. JAVA JAVA面试题和项目面试核心要点精华总结(想进大公司必看)

热门文章

  1. Spring 是如何解决循环依赖的?
  2. Redis 核心篇:唯快不破的秘密
  3. MySQL下载地址与Centos7安装MySQL以及启动问题排查
  4. 客户端负载均衡Ribbon
  5. Spring Cloud与Docker——微服务架构概述
  6. linux驴杂记
  7. linux环境变量 shell变量 command not found解决方法(转)
  8. mysql高级day1
  9. LSTM机器学习生成音乐
  10. linux(4)Linux 文件内容查看