面向亿行 C/C++ 代码的静态分析系统设计及实践-肖枭
面向亿行C/C++代码的 静态分析系统设计及实践 肖枭 自我介绍 2016年香港科技大学取得博士学位 过去10年一直以极高的热情从事静态 分析技术的学术用研究 合作创办源伞科技,致力于推动静态 分析技术在企业中的应用 目录 代码质量管理是个大问题 静态分析+代码评审的实践 学习和强调,红线和惩罚,100%的测试 覆盖率,和事后复盘并不够 有经验的程序员也会犯错 对代码提要求很难监督落实 软件工程师一天被邀请进行多次 代码评审,这些都不是他们自身 的KPI • 一旦工期紧996,人工评审容易 变成走形式 • 任务挂着还容易造成工程师焦虑 降低工程师劳动强度 大规模C/C++静态代码评审系统搭建 数千个活跃开发 的代码仓库 每天上千次代码 评审请求 平均每次代码评 审小于50分钟 • 需要编译C/C++代码 • 使用了定理证明器求解可 行路径(精确,耗时) • 能跨函数分析 150 200 250 300 不编译 编译 报告数 编译流程融合静态分析 分布式编译与分析 大量使用缓存 提升静态分析的理论速度 如何做到10分钟反馈分析结果 系统地改进分析时间 编译流程 分析流程 依赖关系分析 分布式 编译 分布式 分析 分布式链接 跨模块分析 报告整合 缓存 缓存 缓存 缓存 硬核玩家:从理论上改进静态分析能力0 码力 | 39 页 | 6.88 MB | 1 年前3《深入浅出MFC》2/e
买了您的译作深入Visual C++ 4.0 后,才认识您这在Windows Programming 著作方面的 头号人物。十分佩服您的文笔,译得通顺流畅,可谓信达雅。之后偶然翻阅您另外的作品 Windows 95 系统程序设计大奥秘与深入浅出MFC,更是对您五体投地,立刻将这两 本书买下来,准备好好享受一下。对于深入浅出MFC,我给予极高的评价,因为它完全 满足我的需要。我去年才从台大电机博士班计算器科学组毕业,目前在资策会信息技术处服 程序开发的工具,但是由于MFC 系统相当庞大,内 容繁杂,并且夹杂着大量令初学者莫明其妙的macros,更加大了学习上的难度。 当今市面上有不少讲解C++ 和VC++ 程序设计的书籍,但C++ 书籍单纯只讲C++,从 C++ 过渡到VC++ 却是初学者的一大难关;大多数讲解VC++ 的书都将重点放在如何使用 Microsoft Developer Studio,很少有对MFC 进行深入而有系统的讲解。而将C++ 美国dengqi@glocom-us.com 侯俊杰先生:您好!从学校出来的七年间,我大多从事embedded system software 的设计。 在大陆,主要从事交换机系统软件的设计,到了美国,主要从事卫星通信地面站系统软件的 设计。程序设计主要结合C 和Assembly。在大陆,embedded system 多采用Intel 的 processor,在美国,embedded system0 码力 | 1009 页 | 11.08 MB | 1 年前3现代C++ 教程:高速上手C++11/14/17/20
进一步阅读的参考资料 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 75 第 8 章文件系统 75 8.1 文档与链接 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 的层面上制定了 std::thread,从而支持了并发编程,在不同平台上不再依赖于系统底层的 API,实现了语言层面的跨 平台支持;std::regex 提供了完整的正则表达式支持等等。C++98 已经被实践证明了是一种非常成功 的『范型』,而现代 C++ 的出现,则进一步推动这种范型,让 C++ 成为系统程序设计和库开发更好的 语言。Concept 提供了对模板参数编译期的检查,进一步增强了语言整体的可用性。 拢,直接学习新特性。毕竟,技术是向前发展的。 1.2 与 C 的兼容性 出于一些不可抗力、历史原因,我们不得不在 C++ 中使用一些 C 语言代码(甚至古老的 C 语言代 码),例如 Linux 系统调用。在现代 C++ 出现之前,大部分人当谈及『C 与 C++ 的区别是什么』时, 普遍除了回答面向对象的类特性、泛型编程的模板特性外,就没有其他的看法了,甚至直接回答『差不 多』,也是大有人在。图0 码力 | 83 页 | 2.42 MB | 1 年前3C++高性能并行编程与优化 - 课件 - 05 C++11 开始的多线程编程
std::milli> 的别名 跨平台的 sleep : std::this_thread::sleep_for • 可以用 std::this_thread::sleep_for 替代 Unix 类操作系统专有的的 usleep 。他可 以让当前线程休眠一段时间,然后继续。 • 而且单位也可以自己指定,比如这里是 milliseconds 表示毫秒,也可以换成 microseconds 表示微秒, 前线程休眠直到某个时间点。 第 1 章:线程 进程与线程 • 进程是一个应用程序被操作系统拉起来加载到内存之后从开始执行到执行结束的这样一个 过程。简单来说,进程是程序(应用程序,可执行文件)的一次执行。比如双击打开一个 桌面应用软件就是开启了一个进程。 • 线程是进程中的一个实体,是被系统独立分配和调度的基本单位。也有说,线程是 CPU 可 执行调度的最小单位。也就是说,进程本身并不能获取 unlock() 这个锁。 案例:实现生产者 - 消费者模式 • 类似于消息队列…… • 生产者:厨师,往 foods 队列里推送食品 ,推送后会通知消费者来用餐。 • 消费者:等待 foods 队列里有食品,没有 食品则陷入等待,直到被通知。 条件变量:将 foods 队列封装成类 std::condition_variable 小贴士 1. std::condition_variable0 码力 | 79 页 | 14.11 MB | 1 年前3C++高性能并行编程与优化 - 课件 - 11 现代 CMake 进阶指南
需要先创建 build 目录 • 切换到 build 目录 • 在 build 目录运行 cmake < 源码目录 > 生成 Makefile • 执行本地的构建系统 make 真正开始构建( 4 进程并 行) • 让本地的构建系统执行安装步骤 • 回到源码目录 现代 CMake 提供了更方便的 -B 和 --build 指令,不同平台,统一命 令! • cmake -B build • --build 命令。 // 在源码目录用 -B 直接创建 build 目录并生成 build/Makefile // 自动调用本地的构建系统在 build 里构建,即: make -C build -j4 // 调用本地的构建系统执行 install 这个目标,即安 装 -D 选项:指定配置变量(又称缓存变量) • 可见 CMake 项目的构建分为两步: 项目的构建分为两步: • 第一步是 cmake -B build ,称为配置阶段( configure ),这时只检测环境并生成构建规则 • 会在 build 目录下生成本地构建系统能识别的项目文件( Makefile 或是 .sln ) • 第二步是 cmake --build build ,称为构建阶段( build ),这时才实际调用编译器来编译代码 • 在配置阶段可以通过 -D 设置缓存变量。第二次配置时,之前的0 码力 | 166 页 | 6.54 MB | 1 年前3C++高性能并行编程与优化 - 课件 - 12 从计算机组成原理看 C 语言指针
也有人说 1 KiB 才是 1024 B 的,但是很少有人采用这种写法…… • 在买硬盘和 u 盘等存储设备的时候,往往会出现容量减少的情况,这是因为生产厂家按照 的是 1000 倍的换算的,而我们的系统中一般都是按照 1024 倍去计算的。 字还被用于表示内存地址 • 字的长度除了决定一次处理的整数大小之外,还决定了能访问的内存地址的范围。 • 这是因为内存是一维排列的,假如内存容量是 65536 是短整数类型,大小为 16 位或者说 2 字节。 int 是整数类型,大小为 32 位或者说 4 字节。 long long 是超长整数类型,大小为 64 位或者说 8 字节。 long 比较特殊,在 Unix 上随系统位数变化, Windows 上始终是 32 位。 C 语言的基础整数类型 类型 Unix 32 位 Unix 64 位 Windows 32 位 Windows 64 位 char 8 位 8 64 位 64 位 注意到 Unix 和 Windows 关于 long 的定义有分歧: Unix 认为 long 的大小应该和系统架构位数一样, 32 位系统上就 32 位, 64 位系统上就 64 位。 Windows 认为 long 不论 32 位系统还是 64 位系统都一样应该为 32 位,认为这样安全。 因此我们在编写 C 语言程序时,应该避免使用 long 类型,他会导致你的程序难以跨平台。0 码力 | 128 页 | 2.95 MB | 1 年前3Hello 算法 1.1.0 C++ 版
从巧夺天工的匠人技艺、 到解放生产力的工业产品、再到宇宙运行的科学规律,几乎每一件平凡或令人惊叹的事物背后,都隐藏着精 妙的算法思想。 同样,数据结构无处不在:大到社会网络,小到地铁线路,许多系统都可以建模为“图”;大到一个国家,小 到一个家庭,社会的主要组织形式呈现出“树”的特征;冬天的衣服就像“栈”,最先穿上的最后才能脱下; 羽毛球筒则如同“队列”,一端放入、另一端取出;字典就像一个“哈希表”,能够快速查找目标词条。 高效地展开阶段二和阶段三的学习。 第 0 章 前言 hello‑algo.com 9 图 0‑8 算法学习路线 0.3 小结 ‧ 本书的主要受众是算法初学者。如果你已有一定基础,本书能帮助你系统回顾算法知识,书中源代码也 可作为“刷题工具库”使用。 ‧ 书中内容主要包括复杂度分析、数据结构和算法三部分,涵盖了该领域的大部分主题。 ‧ 对于算法新手,在初学阶段阅读一本入门书至关重要,可以少走许多弯路。 ,每轮执行求和操作,即可求得 ?(?) 。 ‧ 递归:将问题分解为子问题 ?(?) = ?+?(?−1) ,不断(递归地)分解下去,直至基本情况 ?(1) = 1 时终止。 1. 调用栈 递归函数每次调用自身时,系统都会为新开启的函数分配内存,以存储局部变量、调用地址和其他信息等。 这将导致两方面的结果。 ‧ 函数的上下文数据都存储在称为“栈帧空间”的内存区域中,直至函数返回后才会被释放。因此,递归 通常比迭代更加耗费内存空间。0 码力 | 379 页 | 18.47 MB | 1 年前3C++高性能并行编程与优化 - 课件 - 16 现代 CMake 模块化项目管理指南
在新模块( Carer )的头文件和源文件中都导入其他模块( Animal )的头 文件。 • 注意不论是项目自己的头文件还是外部的系统的头文件,请全部统一采用 < 项目名 / 模块名 .h> 的格式。不要用 “模块名 .h” 这种相对路径的格式,避 免模块名和系统已有头文件名冲突。 十、依赖其他模块但不解引用,则可以只前向声明不导入头文件 • 如果模块 Carer 的头文件 Carer.h 中则是基于定义者所在路径,优先访问定义者的作用域。这里需要 set(key val PARENT_SCOPE) 才能修改到外面的变量。 第二章:第三方库 / 依赖项配置 用 find_package 寻找系统中安装的第三方库并链接他们 find_package 命令 • 常用参数列表一览: • find_package([version] [EXACT] [QUIET] Config.cmake 的文件,我称之为包配置文件。 • Qt5Config.cmake 是你安装 Qt5 时,随 libQt5Core.so 等实际的库文件,一起装到你的 系统中去的。以我的 Arch Linux 系统为例: • 包配置文件位于 /usr/lib/cmake/Qt5/Qt5Config.cmake 。 • 实际的动态库文件位于 /usr/lib/libQt5Core.so 。 0 码力 | 56 页 | 6.87 MB | 1 年前3Hello 算法 1.0.0 C++版
高效地展开阶段二和阶段三的学习。 第 0 章 前言 hello‑algo.com 9 图 0‑8 算法学习路线 0.3 小结 ‧ 本书的主要受众是算法初学者。如果你已有一定基础,本书能帮助你系统回顾算法知识,书中源代码也 可作为“刷题工具库”使用。 ‧ 书中内容主要包括复杂度分析、数据结构和算法三部分,涵盖了该领域的大部分主题。 ‧ 对于算法新手,在初学阶段阅读一本入门书至关重要,可以少走许多弯路。 ,每轮执行求和操作,即可求得 ?(?) 。 ‧ 递归:将问题分解为子问题 ?(?) = ?+?(?−1) ,不断(递归地)分解下去,直至基本情况 ?(1) = 1 时终止。 1. 调用栈 递归函数每次调用自身时,系统都会为新开启的函数分配内存,以存储局部变量、调用地址和其他信息等。 这将导致两方面的结果。 ‧ 函数的上下文数据都存储在称为“栈帧空间”的内存区域中,直至函数返回后才会被释放。因此,递归 通常比迭代更加耗费内存空间。 间效率上与迭代相当。这种情况被称为「尾递归 tail recursion」。 ‧ 普通递归:当函数返回到上一层级的函数后,需要继续执行代码,因此系统需要保存上一层调用的上下 文。 ‧ 尾递归:递归调用是函数返回前的最后一个操作,这意味着函数返回到上一层级后,无须继续执行其他 操作,因此系统无须保存上一层函数的上下文。 以计算 1 + 2 + ⋯ + ? 为例,我们可以将结果变量 res 设为函数参数,从而实现尾递归:0 码力 | 378 页 | 17.59 MB | 1 年前3C++高性能并行编程与优化 - 课件 - 01 学 C++ 从 CMake 学起
中的字符串(称为源码),并根据 C+ + 标准生成相应的机器指令码,输出到 a.out 这个文件中,(称为可执行文件)。 • > ./a.out • 之后执行该命令,操作系统会读取刚刚生成的可执行文件,从而执行其中编译成机器码, 调用系统提供的 printf 函数,并在终端显示出 Hello, world 。 厂商 C C++ Fortran GNU gcc g++ gfortran LLVM clang -c 选项指定生成临时的对象文件 main.o ,之后再根据一系列对象文件进行链接 ,得到最终的 a.out : • > g++ hello.o main.o -o a.out 为什么需要构建系统( Makefile ) • 文件越来越多时,一个个调用 g++ 编译链接会变得很麻烦。 • 于是,发明了 make 这个程序,你只需写出不同文件之间的依赖关系,和生成各文件的规则。 • > make 但坏处也很明显: 1. make 在 Unix 类系统上是通用的,但在 Windows 则不然。 2. 需要准确地指明每个项目之间的依赖关系,有头文件时特别头疼。 3. make 的语法非常简单,不像 shell 或 python 可以做很多判断等。 4. 不同的编译器有不同的 flag 规则,为 g++ 准备的参数可能对 MSVC 不适用。 构建系统的构建系统( CMake ) • 为了解决 make0 码力 | 32 页 | 11.40 MB | 1 年前3
共 25 条
- 1
- 2
- 3