欢迎光临散文网 会员登陆 & 注册

Carbon Language - C++20/C++23 - Sanitizer

2023-02-20 11:48 作者:紧果呗  | 我要投稿

书接上一篇 ## 🟡 Carbon Language,在 Windows 系下运行失败。目前只能通过 Windows WSL 系统体验 Carbon。

Carbon 语言当前的实现称为 Explorer,其主要目的是作为语言的明确规范,官方提供在线体验网站,它是基于 LLVM 现代编译器框架开发的一个前端编译器。

作为该目标的一个扩展,Explorer 还可以用作原型设计和验证语言更改的平台。因此,它优先于展示直接可读的代码,其次是性能、诊断质量和其他常规实现。换言之,它的目标受众是从事 Carbon 设计的人,而不是任何Carbon 编程终端用户。

  • - [Building on Windows](https://github.com/carbon-language/carbon-lang/issues/298)

  • - [Carbon on Windows WSL](https://cristianopizzamiglio.com/2022/08/14/carbon-wsl.html)

  • - [C++ Standard Libraries](https://docs.brew.sh/C++-Standard-Libraries)

  • - [So I tried Carbon... Aryan Garg](https://aryan401.hashnode.dev/carbon)

注意安装基础编译工具套件或 clang 编译器,Brew 需要用它来编译 glibc 等基础库:

GCC 10.9 开始基础运行库命名为 libc++,早期的版本则默认为 libstdc,可以按需要安装指定版本。

    brew install gcc@7

    brew install --cc=gcc-7 <formula>

最后编译时通过了,也生成了 explorer,但是执行时,未能通过 Sanizer 内存安全检查:

# https://github.com/carbon-language/carbon-lang/issues/2236

总之,安装过程非常不顺利,还是官方说的那样,如果可以使用 Rust,那就不必考虑 Carbon!

Cargo explorer 项目构建脚本

这个项目由谷歌内部 C++ 和开发工具组开启,因为 C++ 标准委员会无法在 C++ ABI 上达成共识。目标是不用重写谷歌内部巨大的 C++ 代码,同时逐步提高安全和执行效率。资源上,最多是主管级的支持。大公司里一个小组放出一个天马行空的开源项目很常见,Google 开源玩具 demo 也是老传统。


演化论有个“生态位”的概念,即在一个稳定的环境下,一个生态位一旦被先来者抢占,那后来者是没有机会的,这个先来者就会一直占着这个生态位,直到环境发生变化。而软件工业中的 C++ 就是这样的一个地位。


自操作系统诞生以来,编写内存安全的代码一直是一个比较困难的问题,另一个问题则是保证线程安全。2004 年以来,微软安全响应中心(MSRC)已对所有报告过的微软安全漏洞进行了分类,据统计数据,所有微软年度补丁中约有 70% 是针对内存安全漏洞的修复程序。

  • - https://github.com/google/sanitizers

  • - https://gcc.gnu.org/onlinedocs/gcc-11.3.0/gcc/Option-Index.html

  • - https://developers.redhat.com/blog/2021/05/05/memory-error-checking-in-c-and-c-comparing-sanitizers-and-valgrind

  • - [Definitions and One Definition Rule (ODR)](https://en.cppreference.com/w/cpp/language/definition)

  • - [Constraints and concepts (since C++20)](https://en.cppreference.com/w/cpp/language/constraints)

  • - [C++ compiler support](https://en.cppreference.com/w/cpp/compiler_support)

Sanitizers 是谷歌发起的开源内存安全检查工具,项目本是 LLVM 项目的一部分,GNU GCC 编译器也集成了。GCC 4.8 版本开始支持地址、线程 Sanitizer,GCC 4.9 版本开始支持 Leak Sanitizer 和 UB Sanitizer,这些都是查找隐藏 Bug 的利器。通过编译器参数启用,如 -fsanitize=address 使用地址检查器。

  • - AddressSanitizer 检查地址相关问题,包括释放后使用、重复释放、堆溢出、栈溢出等等问题。

  • - LeakSanitizer 检查内存泄漏问题。

  • - ThreadSanitizer 检查线程数据竞争和死锁问题。

  • - MemorySanitizer 检查使用未初始化内存问题。

  • - Undefied Behavior Sanitizer 未定义行为问题。

Address Sanitize 支持功能:

  • 01. Use after free (dangling pointer dereference)  使用悬浮指针

  • 02. Heap buffer overflow    堆缓冲区溢出

  • 03. Stack buffer overflow   栈缓冲区溢出

  • 04. Global buffer overflow  全局缓冲区溢出

  • 05. Use after return        通过返回值访问局部变量的内存

  • 06. Use after scope         访问已经释放的局部变量的内存

  • 07. Initialization order bugs   使用未初始化的内存

  • 08. Memory leaks            内存泄漏

C++20 是有史以来最大的 C++ 版本更新,但是不知什么原因它又没有完全完工,是疫情版完成了后续的工作,C++23 “Pandemic Edition” is complete。要使用最新的功能,需要 GCC 或 CLang 13 这样的版本。


C++20 引入了一个新概念,真的是概念,它的名字就叫 `concept`,其实是一个语法糖,它的本质可以认为是一个模板类型的 bool 变量。

    template < template-parameter-list >

    concept  concept-name = constraint-expression;

其中,constraint-expression 是一个可以被 eval 为 bool 的表达式或者编译期函数。使用定义好的 concept 时,constraint-expression 会根据上面 template-parameter-list 传入的类型,执行编译期计算,判断使用该concept的模板定义是否满足。 如果不满足,则编译期会给定一个具有明确语义的错误,即这个 concept 没有匹配成功。 注意到,上述匹配的行为都是在编译期完成的,因此 concept 是 zero-cost 表达式。


Multiple declarations, Only one definition。


对于编译器来说,任何一个翻译单元中,只允许对任何变量、函数、类类型、枚举类型、`concept` 或模板进行一个定义。其中一些可能有多个声明,但是定义只允许一个,这就是 ODR 单一定义规则。


在整个程序中,包括标准库和用户定义库,ODR 规则使用的 non-inline 函数或变量只需要出现一个定义。编译器不需要诊断这种违反,但违反它的程序的行为是未定义的,即 ODR Violation。


遵循 ODR 是构建良好 C++ 程序的基础。编写 C++ 程序时,代码写在文件中,然而对于 ODR 原则来说,文件之间的边界并不很重要,真正重要的是编译单元,Translation Units。本质上来说,一个编译单元是对程序员提交给编译器的文件执行预处理后的结果,即一个源文件经过预处理后,产生一个目标文件。参考 C++ template:the complete guide。


预处理器按照条件编译命令,#if,#ifdef 等等,去除掉未被选中的代码块,去除注释,递归地插入 "#include" 指令所引用的文件,并将宏展开。


Valgrind 可以检测非常多的内存错误,但相对于 Sanitizer,对程序性能影响更大。


以下测试程序一般编译通过并正常运行,但是使用内存检查工具后,就可以发现潜在的越界问题:


Carbon Language - C++20/C++23 - Sanitizer的评论 (共 条)

分享到微博请遵守国家法律