释放结束了原来的访问条件
动态分配把一段存储交给程序使用,释放后,内存管理器可以回收或重新分配它。仍保存旧地址的指针不会因此继续拥有原来的对象,后续读取或写入可能使用已经失效的内容。
程序没有立刻崩溃不能证明访问合法。SEI CERT说明,释放后的内容可能暂时保持原样,也可能意外改变;依赖这种表象,会让缺陷只在某些分配顺序或运行负载下显现。
最后一次访问必须先于释放
链表清理能说明一种常见错误:释放当前节点之后,再读取它的next字段,已经是在访问释放后的节点。需要先保存下一节点的信息,再释放当前节点;单纯把释放语句放进循环,并不能保证访问顺序正确。
多个持有者使责任更难辨认:一个路径释放对象,另一路径却还保留访问能力。所有权、借用或受管理的共享持有关系,应让释放责任与仍然允许的使用保持一致,而不是只在某一处清空一个指针变量。
检测访问,也核对资源管理
AddressSanitizer的示例先分配数组、删除数组,再读取其中元素,工具报告访问位置以及先前的分配和释放位置。这类记录能把距离很远的获取、释放和错误使用联系起来,帮助找出错误责任边界。
修复不能一概变成永不释放,否则可能把非法访问换成持续泄漏。应先确定对象的真实最后使用者与生命期;若仍需传递数据,可以转移所有权、保留受管理的共享持有关系,或复制所需内容,并核对各自成本与约束。