stanford cs 110l lec2

为什么放弃cpp,选择rust

  • 因为cpp存在大量的memory safety
    • 空悬指针,返回指向栈中的变量的指针Rust编译器会对其做识别
    • double freeRust编译器保证一旦内存被释放,那么就不能够去使用该内存
    • 访问已经释放的内存Rust编译器使得我们不能够去修改n指向的数据
    • 内存泄漏这里不就是GC吗

语言与编译器

  • 由于Rust的限制,也就是编译器过于保守,一些程序很难写出并通过编译器的检查,这时就需要unsafe关键字Rust的高新能得益于其编译器的优化

owership

  • 基本数据类型的CopyTrait
  • 对于refernece(引用),在可变作用域内,只能存在一个可变引用。对于不可变引用,可以存在多个

Lifetimes

  • 对于已经超出了作用域的变量,Rust编译器会调用drop函数(destructor)去回收其内存?

1如何找到程序中的bugs

1.1 动态分析

  • 通过你给的输入数据,运行代码,检测错误行为。通常会在运行代码时,附带一些技术,并尝试大量的不同的输入数据(fuzzing模糊测试)

valgrind

  • 将二进制代码反汇编,并对代码打桩,valgrind会使用一些元数据,来记录内存的使用情况,以此检测内存的错误
  • valgrind并不能够检测处gets函数的错误,因为stack就是一段内存,但是其中的变量被覆盖了,并不会被valgrind检测出来。

LLVM Sanitizers

  • 做修饰,但是是在源代码级别上的。
  • 因为有更多的信息可以利用,在编译之前,sanitizers可以利用这些信息做处理
  • 有很多的Sanitizer
    • AddressSanitizer,用于检测内存越界,doule free,使用释放后的内存
    • LeakSanitizer,找到内存泄漏
    • MemorySanitizer,找到使用未初始化的内存
    • UndefinedBehaviorSanitizer, 找到使用空指针,整数/浮点溢出
    • ThreadSanitizer,不恰当的使用线程

动态分析的限制

  • 动态分析只能够发现运行时出现的错误,如果输入的样例不足,那么一些错误边界条件难以检测到,可以通过fuzzing勉强处理,不一样的control flow graph

1.2 静态分析

linting

  • linter,(来自于,衣服在烘干机中脱落的纤维绒毛,那么linter就是像烘干机中的绒毛(lint)过滤器), clang-tidy甚至可以自动修复很多问题。

dataflow analysis

  • 动态追踪数据的变化
    • 在这里toMakeUppercase可能是一个未初始化的值
    • if 语句(statement与expression的区别在于expression有值)多处返回造成的内存泄漏,RAII出现的原因
    • call与if statement类似,会出现可能的leak of memory
  • 静态分析存在false positives的缺点,也就是可能会把不可能的错误报出。以及代码中如果存在过多的分支以及条件判断,那么可能静态分析的性能会很低,这其中存在着一个效率与全面性的权衡,

参考

posted @ 2022-06-03 19:35  抿了抿嘴丶  阅读(114)  评论(0编辑  收藏  举报