一、应对并发Bug方法
1、防御性编程
assert(); 测试某个关键变量或条件
CHECK_HEAP(p); //指针地址在堆区
二、死锁和数据竞争
1、死锁,线程之间相互等待
避免死锁
死锁产生的必要条件
(1)互斥:一个资源每次只能被一个进程使用
(2)请求与保持:一个进程请求资源阻塞时,不释放已经获取的资源
(3)不剥夺:进程已经获得的资源不能被强行剥夺
(4)循环等待:若干进程之间形成头尾相接的循环资源关系
AA-Deadlock
(1)AA型死锁容易检测,及早报告,及早修复
(2)spinlock-xv6.c中的各种防御性编程
if(holding(lk)) panic();
ABBA-Deadlock
(1) 任意时刻系统中的锁都是有限的
(2)严格按照固定顺序获得所有锁(消除循环等待)
2、数据竞争(不同线程同时访问同一段内存,且至少有一个是写)
使用互斥锁保护共享数据
互斥锁-原子性
条件变量-同步
3、Lockdep与threadSanitizer
Lockdep:运行时死锁检查
(1)Lockdep规约(Specification)
为每一个锁确定唯一的“allocation site”
threadSanitizer:运行时数据竞争检查
(1)为所有事件建立happens-before关系圈
Program-order+release-acquire
对于发生的不同线程且至少有一个写的检查
更多的检查:动态程序
(1)在事件发生时记录
Lockdep:lock/unlock
ThreadSanitzer:内存访问+lock/unlock
三、动态分析工具
1、AddressSanitizer:非法内存访问
Buffer(heap/stack/global)overflow,use-after-free,use-after-return,double-free
2、ThreadSanitizer:数据竞争
3、MemorySanitizer:未初始化的读取
4、UBSanitizer:undefine behavior
Misaligned pointer,signed integer overflow
Kernel会带着-fwrapv编译
MSVC:Debug遇到的事情
未初始化的栈:0xcccccccc(GB2312:烫烫)
未初始化的堆:0xcdcdcdcd(GB2312:屯屯)
对象头尾:0xfdfdfdfd
已回收内存:0xdddddddd(GB2312:茸茸)