Rust被称为内存安全语言,但GCC中有一个名为AddressSanitizer(ASAN)的安全功能:
./configure CFLAGS="-fsanitize=address -g" CXXFLAGS="-fsanitize=address -g" LDFLAGS="-fsanitize=address"
make
make check
ASAN可以提供与Rust相同的内存安全性,还是Rust有更多技巧?甚至可以比较两者吗?
免责声明:我不是程序员。
答案 0 :(得分:13)
清洁剂
GCC和Clang都有一个套件的消毒剂;到目前为止,它们是在Clang开发的,然后移植到GCC,所以Clang拥有最先进的版本:
Type Sanitizer还有正在进行的工作。
Sanitizers vs Rust
不幸的是,使用消毒剂使C ++达到Rust的安全水平是不可能的;即使合并所有现有的消毒杀菌剂仍然会留下空白,众所周知它们是不完整的。
您可以在CppCon 2017看到John Regher关于未定义行为的演示文稿,幻灯片can be found on github,我们可以从中获得当前的报道:
这并不能解释消毒杀菌剂彼此不相容的事实。也就是说,即使你愿意接受组合的减速(15x-45x?)和内存开销(15x-30x?),你仍然不能管理C ++程序和Rust那样安全。 / p>
强化与调试
消毒剂之所以如此占用CPU /内存是因为它们是调试工具;他们试图尽可能精确地为开发人员提供诊断,以便对调试最有用。
要在生产中运行代码,您要查找的是强化。强化是指以尽可能低的开销消除未定义的行为。例如,Clang支持多种方法来强化二进制文件:
这些工具可以组合在一起,并且对性能影响最小(<1%)。不幸的是,它们比清洁剂的覆盖范围要小得多,最值得注意的是,它们并不试图涵盖使用后使用/使用后范围或数据竞争,这些都是攻击的常见目标。
<强>结论强>
我没有看到任何方法将C ++提升到Rust结合的安全级别,没有:
另一方面,值得注意的是Rust本身使用unsafe
代码;并且其unsafe
代码也需要经过审查(参见Rust Belt project),并将受益于所有上述消毒剂/硬化仪器通过。
答案 1 :(得分:2)
不,这两个功能无法比较。
地址清理不是安全功能,也不提供内存安全性:它是一种调试工具。程序员已经有工具来检测他们编写的代码是否存在内存问题,例如free-after-free或内存泄漏。 Valgrind可能是最着名的例子。这个gcc功能提供了(某些)相同的功能:唯一的新功能是它与编译器集成,因此更容易使用。
您不会在生产中启用此功能:它仅用于调试。您使用此标志编译测试,并自动检测由测试触发的内存错误。如果您的测试不足以触发问题,那么您仍然遇到问题,并且它仍然会在生产中造成相同的安全漏洞。
Rust的所有权模型通过使包含此类缺陷的程序无效来防止这些缺陷:编译器不会编译它们。您不必担心测试不会触发问题,因为如果代码编译,则不会出现问题。
这两个功能适用于不同的问题。地址清理的一个特征是检测内存泄漏(分配内存并忽略以后释放内存)。 Rust使得编写内存泄漏比在C或C ++中更难,但它仍然可能(如果你有循环引用)。 Rust的所有权模型可防止顺序和多线程情况下的数据争用(见下文)。地址清理并不旨在发现这两种情况。
顺序代码中数据竞争的一个示例是,如果您在一组对象上进行迭代,同时还要添加或删除元素。在C ++中,更改大多数集合将使任何迭代器无效,但是程序员必须意识到这已经发生:它未被检测到(尽管某些集合在调试版本中有额外的检查)。在Rust中,当它上面存在迭代器时,不可能改变集合,因为所有权模型会阻止它。
多线程代码中的数据争用的一个示例是具有两个共享对象的线程,其中访问由互斥锁保护。在C ++中,程序员可能会在更改对象时忘记锁定互斥锁。在Rust中,互斥锁本身拥有它保护的对象,因此不可能不安全地访问它。 (但是还有许多其他类型的并发错误,所以不要被带走!)
答案 2 :(得分:-1)
没有听说过这个选项,但听起来它修改了输出程序。换句话说,它会在程序运行时进行检查。
另一方面,Rust会检查程序何时创建(或在程序员中编译),因此首先没有这些内存安全漏洞。链接文章提到它无论如何只涵盖一个案例,返回后使用。