Can GCC';s ASAN提供与Rust相同的内存安全性?

Can GCC';s ASAN提供与Rust相同的内存安全性?,gcc,rust,address-sanitizer,Gcc,Rust,Address Sanitizer,Rust是一种内存安全语言,但GCC中有一个安全特性,称为(ASAN): /configure CFLAGS=“-fsanitize=address-g”cxflags=“-fsanitize=address-g”LDFLAGS=“-fsanitize=address” 制作 核对 ASAN能否提供与Rust相同的内存安全性,或者Rust是否有更多的技巧?甚至可以将两者进行比较吗 免责声明:我不是程序员 还没听说过这个选项,但听起来好像它修改了输出程序。换句话说,它在程序运行时进行检查 另一方

Rust是一种内存安全语言,但GCC中有一个安全特性,称为(ASAN):

/configure CFLAGS=“-fsanitize=address-g”cxflags=“-fsanitize=address-g”LDFLAGS=“-fsanitize=address”
制作
核对
ASAN能否提供与Rust相同的内存安全性,或者Rust是否有更多的技巧?甚至可以将两者进行比较吗


免责声明:我不是程序员

还没听说过这个选项,但听起来好像它修改了输出程序。换句话说,它在程序运行时进行检查

另一方面,Rust会检查程序的创建时间(或者用程序员的话说编译),所以一开始就不存在这些内存安全缺陷


链接文章提到它只涉及一个案例,返回后使用

不,这两个特征不可比较

地址清理不是一种安全功能,也不提供内存安全:它是一种调试工具。程序员已经有了一些工具来检测他们编写的代码是否存在内存问题,例如空闲后使用或内存泄漏。Valgrind可能是最著名的例子。这个gcc特性提供了(部分)相同的功能:唯一的新功能是它与编译器集成,因此更易于使用

您不会在生产环境中启用此功能:它仅用于调试。使用此标志编译测试,测试会自动检测由测试触发的内存错误。如果您的测试不足以触发问题,那么您仍然存在问题,并且仍然会在生产中导致相同的安全缺陷

Rust的所有权模型通过使包含这些缺陷的程序无效来防止这些缺陷:编译器不会编译它们。您不必担心测试不会触发问题,因为如果代码编译,就不会有问题

这两个特性适用于不同的问题集。地址清理的一个特性是检测内存泄漏(分配内存而忽略以后释放内存)。RIST比C或C++更难编写内存泄漏,但仍然是可能的(如果你有循环引用)。Rust的所有权模型防止了顺序和多线程情况下的数据竞争(见下文)。地址消毒的目的不是检测这两种情况

顺序代码中的数据竞争的一个例子是,如果您在对象集合上进行迭代,同时添加或删除元素。在C++中,改变大多数集合会使任何迭代器无效,但程序员必须意识到这一点:没有检测到(虽然有些集合在调试构建中有额外的检查)。在Rust中,当集合上存在迭代器时,不可能对集合进行变异,因为所有权模型阻止了这一点


多线程代码中的数据竞争的一个例子是,两个线程共享一个对象,访问受互斥锁保护。在C++中,程序员可以在改变对象时忘记锁定互斥体。在Rust中,互斥锁本身拥有它所保护的对象,因此不可能不安全地访问它。(不过,还有许多其他类型的并发错误,所以不要忘乎所以!)

消毒剂

GCC和Clang都有一套消毒剂;到目前为止,它们是在Clang中开发的,然后移植到GCC,因此Clang拥有最先进的版本:

  • (ASan):检测越界访问、释放后使用、作用域后使用、双重释放/无效释放,并增加对内存泄漏的支持(预期内存开销为3倍)
  • (MemSan):检测未初始化的读取(预期慢3倍)
  • (TSan):检测数据争用(预期速度为5x-15x,内存开销为5x-10x)
  • (UBSan):各种本地未定义行为,如未对齐指针、整数/浮点溢出等。。。(最低速度减慢,代码大小略有增加)
还有一项工作正在进行中


消毒剂与防锈剂的对比

不幸的是,不可能使用杀菌剂使C++达到锈病的安全水平;即使将所有现有的消毒剂组合在一起,仍然会留下空白,众所周知,它们是不完整的

您可以在幻灯片上看到John Regher关于未定义行为的演示,我们从中获得当前的报道:

这并不能解释清洁剂彼此不兼容的事实。也就是说,即使您愿意接受组合的减速(15X-45 x?)和内存开销(15x30x?),您仍然不能管理C++程序的安全性。
强化与调试

清理器如此需要CPU/内存的原因是因为它们是调试工具;它们试图为开发人员提供尽可能精确的诊断,以便对调试最有用

对于在生产环境中运行代码,您需要的是强化。强化是指以尽可能低的开销消除未定义的行为。例如,Clang支持多种硬化二进制文件的方法:

  • (CFI):防止控制流hi劫持(虚拟调用、间接调用等)
  • :防止堆栈缓冲区溢出
  • 未定义的行为消毒剂
这些工具可以组合使用,对性能的影响最小(<1%)。不幸的是,它们比消毒剂覆盖的范围要小得多,而且最明显的是,它们不试图覆盖免费使用/范围后使用或数据竞争,而这些都是经常受到攻击的目标


结论

我没有看到任何方式将C++带入RID结合的安全级别,没有任何一个:

  • 对语言的严格限制:参见MISRA/JSF指南
  • 非常严重的性能损失:消毒剂、消毒剂