高完整性系统工程(十二):Separation Logic for Automated Verification

news2024/11/16 1:38:00

目录

1. INTRODUCTION TO SEPARATION LOGIC 分离逻辑

1.1 霍尔推理(Hoare Reasoning)

1.2 堆指针的影响

1.3 全局和局部推理(Global and Local Reasoning)

1.4 组合推理(Compositional Reasoning)

1.5 The Frame Rule

1.6 The Side Condition 

1.7 Validity of Triples 三元组的有效性

1.8 Memory Safety 内存安全性

2. A LITTLE MORE FORMALLY

2.1 Expressions, Commands

2.2 Heap Read Rule (Simplified)

2.3 Assignment Rules

2.4 Frame Rule

2.5 Example Proof 

​编辑

2.6 Inductive Predicates 

2.7 Example: Tail


1. INTRODUCTION TO SEPARATION LOGIC 分离逻辑

1.1 霍尔推理(Hoare Reasoning)

霍尔推理是一种用于推理程序正确性的形式化方法,其主要组成部分是霍尔三元组(Hoare Triple):{P} prog {Q},表示在前置条件P成立的情况下,执行程序prog,之后后置条件Q会成立。对于局部变量x和y,这种推理方式在x和y不相互引用(即不能为别名)的情况下才有效。

  • 赋值规则(ASSIGN):{Q[e/x]} x := e {Q},这个规则表示,如果在赋值后的状态Q中将x替换为表达式e可以得到前置状态,那么这个霍尔三元组是有效的。

  • 顺序规则(CONSEQ):(P → P’ {P’} prog {Q’} Q’ → Q) / ({P} prog {Q}),这个规则表示,如果从前置条件P可以推导出另一个前置条件P’,并且从后置条件Q’可以推导出另一个后置条件Q,那么原本的霍尔三元组的效果可以通过新的三元组来实现。

这两个规则在处理基本赋值语句和逻辑推导时十分有用。但是,它们在处理指针和别名等更复杂的数据结构时会变得不够用。

1.2 堆指针的影响

在处理像 *x := 2 这样的语句时,我们需要引入一种新的断言,称为映射断言(Maps-To Assertion):p ↦ e,表示通过p识别的堆位置保存了值e。但这并不能完全解决问题,因为当x和y指向同一个位置,也就是别名的情况时,这个霍尔三元组就会失效。因此,我们需要一种能够处理别名情况的方法。

1.3 全局和局部推理(Global and Local Reasoning)

在霍尔逻辑中,谓词P和Q都是对全局状态进行描述的。这在处理全局变量或者独立的局部变量时没有问题,但是在处理像堆这样的共享结构时就会变得复杂。

为了解决这个问题,分离逻辑引入了一种新的想法:谓词P只描述它关心的状态部分,这部分被称为谓词的领域(也叫足迹),记作 dom(P)。对于映射断言 p ↦ e,它的领域就是{p}。

1.4 组合推理(Compositional Reasoning)

分离逻辑引入了一种新的连接符:分离连词 P ⋆ Q,表示P和Q各自描述了各自的状态部分,并且这两部分是分离的。这就为处理别名问题提供了一种手段。在 P ⋆ Q 中,如果 P 和 Q 有共同的领域,那么 P ⋆ Q 就无法成立。这可以用来表达 x 和 y 不可能是别名的情况。

1.5 The Frame Rule

分离逻辑的一个重要理论是帧规则(FRAME Rule):({P} prog {Q} modv(prog) ∩ fv(R) = {}) / ({P ⋆ R} prog {Q ⋆ R})。这个规则的意思是,如果一个程序没有修改R中的任何变量,那么就可以从{P} prog {Q}推导出{P ⋆ R} prog {Q ⋆ R}。也就是说,如果我们知道在P的情况下执行prog可以得到Q,那么在P和R同时成立的情况下执行prog,我们不仅可以得到Q,还可以得到R。

1.6 The Side Condition 

在上述帧规则中,有一个旁注条件:程序修改的变量集合和R中的自由变量集合不相交。如果这个条件不成立,那么我们就无法保证R在程序执行后仍然成立。

1.7 Validity of Triples 三元组的有效性

在分离逻辑中,霍尔三元组{P} prog {Q}的含义是部分正确性(Partial Correctness):如果P在程序开始时成立,那么只要程序正常终止,Q就会成立,而且,程序绝对不会出错。

1.8 Memory Safety 内存安全性

在一个所有内存不安全访问都会导致失败的语言语义中,分离逻辑可以保证内存安全。比如访问一个未初始化的指针这样的情况,在分离逻辑中是不被允许的。 

2. A LITTLE MORE FORMALLY

2.1 Expressions, Commands

表达式 (e) 是指可以由变量 (x) 或数字 (n) 组成的。它可以提及局部变量,但不能提及堆。表达式在一个存储 s 中求值,其中 s 是一个函数,将变量映射到整数上。

命令 (c) 是构造程序的基本元素。以下是一些基本的命令类型:

  • c1 ; c2:命令序列,首先执行c1,然后执行c2。
  • if e then ct else cf:条件语句,如果表达式 e 为真,则执行 ct,否则执行 cf。
  • while e do c:循环语句,只要表达式 e 为真,就执行命令 c。
  • x := e:将表达式 e 的值赋给变量 x。
  • x := *e:将地址 e 所在的值赋给变量 x。
  • *e1 := e2:将表达式 e2 的值写入到地址 e1 所在的位置。

注意:堆和存储的更新在语法上是不同的。

2.2 Heap Read Rule (Simplified)

堆读取规则描述了从堆中读取数据的过程。简化版的堆读取规则为:

  • 当变量x不在表达式e的地址集(ars(e))中时,我们可以读取存储位置e,得到值v,并将其赋值给x。也就是说,我们可以这样写:{e ↦ v} x := *e {x = v},表示将存储位置e的值v赋给变量x。

这个规则的应用例子:

  • 如果s(y) = 19,执行命令x := *(y+1),并且如果y+1 ↦ 3 holds,那么执行后s(x) = 3。也就是说,将y+1的存储位置中的值3赋给了x。

如果变量 x 在表达式 e 的地址集中,我们需要更一般的规则,但这已超出了本次课程的讨论范围。

2.3 Assignment Rules

  • HEAPW {e1 ↦ _} *e1 := e2 {e1 ↦ e2}:这是堆写入规则,表示将表达式 e2 的值写入到存储位置 e1 所在的位置。
  • ASSIGN {x ≐ n} x := e {x ≐ e[n/x]}:这是基本赋值规则,表示将表达式 e 的值赋给变量 x。这里的 e[n/x] 表示将表达式 e 中的 x 替换为 n。
  • ASSIGN’ (x /∉ vars(e)) / ({emp} x := e {x ≐ e}):这是特殊的赋值规则,只有当变量 x 不在表达式 e 中时,才可以使用。这表示将表达式 e 的值赋给变量 x。

2.4 Frame Rule

Frame 是一种用于跟踪命令 c 修改了哪些变量的工具。以下是一些基本的规则:

  • modv(x := e) = {x}:表示命令 x := e 修改了变量 x。
  • modv(x := *e) = {x}:表示命令 x := *e 修改了变量 x。
  • modv(*e1 := e2) = {}:表示命令 *e1 := e2 没有修改任何变量。
  • modv(while e do c) = modv(c):表示 while 循环修改了 c 修改的所有变量。
  • modv(if e then ct else cf) = modv(ct) ∪ modv(cf):表示 if 语句修改了 ct 和 cf 修改的所有变量。
  • modv(c1 ; c2) = modv(c1) ∪ modv(c2):表示命令序列 c1 ; c2 修改了 c1 和 c2 修改的所有变量。

Frame 规则 ({P} prog {Q} modv(prog) ∩ fv(R) = {}) / ({P ⋆ R} prog {Q ⋆ R}):表示如果 prog 修改的变量与 R 的自由变量 fv(R) 没有交集,则可以在 P 和 Q 上加一个 R 来得到新的断言。

2.5 Example Proof 

这个程序的目的是交换两个指针x和y所指向的值。首先,我们初始化t和u为x和y的值,然后将u和t的值分别赋给x和y。根据Hoare逻辑,我们可以为这个过程创建三元组,并对每个步骤应用Hoare序列规则(Hoare sequencing rule)。Hoare序列规则是用于组合程序语句的一个规则,它允许我们将两个或多个程序语句串联在一起,并形成一个具有前提和后置条件的新的程序语句。

这个过程如下:

  1. {x ↦ vx ⋆ y ↦ vy} t := *x; {(x ↦ vx ∧ t = vx) ⋆ y ↦ vy}
  2. {(x ↦ vx ∧ t = vx) ⋆ y ↦ vy} u := *y; {(x ↦ vx ∧ t = vx) ⋆ (y ↦ vy ∧ u = vy)}
  3. {(x ↦ vx ∧ t = vx) ⋆ (y ↦ vy ∧ u = vy)} *x := u; {(x ↦ u ∧ t = vx) ⋆ (y ↦ vy ∧ u = vy)}
  4. {(x ↦ u ∧ t = vx) ⋆ (y ↦ vy ∧ u = vy)} *y := t; {x ↦ vy⋆ y ↦ vx}

在以上过程中,x ↦ vx表示指针x指向值vx,⋆表示堆中的分隔,即表示x和y指向的是堆中的不同位置。

2.6 Inductive Predicates 归纳谓词

归纳谓词是一种描述堆的工具,可以处理大小不定的堆。比如,e1 ↦ e2 和 emp 只能描述大小为 1 和 0 的堆,但我们如何描述更大的、或者说无界的堆数据结构呢?

例如,我们定义一个归纳谓词 list(e) 来表示一个链表。list(e) 的定义如下:(e = 0 ∧ emp) ∨ (∃e’. e ↦ e’ ⋆ list(e’))。也就是说,如果 e 是 0,那么表示一个空的链表;否则,e 指向一个元素 e’,并且 e’ 后面跟着一个链表。

2.7 Example: Tail

以下是一个使用了上述规则和概念的例子。这是一个简单的交换 x 和 y 的值的程序。

所以,我们成功地证明了这个程序可以交换 x 和 y 的值。

  1. 首先,我们假设 {x ↦ vx ⋆ y ↦ vy}。也就是说,变量 x 的值是 vx,变量 y 的值是 vy。

  2. 执行 t := *x。根据堆读取规则,我们可以将 x 的值 vx 赋给 t。所以,我们得到新的断言 {(x ↦ vx ∧ t = vx) ⋆ y ↦ vy}。

  3. 执行 u := *y。根据堆读取规则,我们可以将 y 的值 vy 赋给 u。所以,我们得到新的断言 {(x ↦ vx ∧ t = vx) ⋆ (y ↦ vy ∧ u = vy)}。

  4. 执行 *x := u。根据堆写入规则,我们可以将 u 的值 vy 写入 x 的位置。所以,我们得到新的断言 {(x ↦ u ∧ t = vx) ⋆ (y ↦ vy ∧ u = vy)}。

    • 执行 *y := t。根据堆写入规则,我们可以将 t 的值 vx 写入 y 的位置。所以,我们得到新的断言 {x ↦ vy⋆ y ↦ vx}。

考虑另一个更复杂的例子,我们想要证明一个操作链表的程序。假设我们有一个链表,它的头是变量 x。

  1. 我们首先假设 {x ≠ 0 ∧ list(x)}。也就是说,x 不是 0,并且它指向一个链表。

  2. 执行 t := *x。根据堆读取规则,我们可以将 x 的值读入 t。所以,我们得到新的断言 {list(t)}。

  3. 为了证明这个断言,我们需要展开 list(t) 的定义。所以,我们得到新的断言 {x ≠ 0 ∧ (∃e’. x ↦ e’ ⋆ list(e’))}。

  4. 由于我们知道 x 的值被赋给了 t,所以我们得到新的断言 {x ≠ 0 ∧ x ↦ e’ ∧ t = e’}。同时,由于 x 指向一个链表,所以我们还有 {x ≠ 0 ∧ x ↦ e’ ∧ t = e’ ⋆ list(e’)}。

这就完成了证明。这个程序将链表的头赋值给了变量 t。

summary

堆是计算机内存中的一种动态数据结构,它通常被用来存储程序运行时产生的数据。然而,要表达堆中数据结构的行为可能非常复杂,因为我们需要考虑到所有可能的内存配置。为了解决这个问题,我们可以使用归纳谓词。

这里的slides中给出的一个归纳谓词的例子是list(e),它用来描述一个列表数据结构,它的定义如下:

list(e) = (e = 0 ∧ emp) ∨ (∃e’. e ↦ e’ ⋆ list(e’))

这个归纳谓词表示,一个列表要么是空的(即e = 0 ∧ emp,emp表示空堆),要么由一个元素和另一个列表组成(即存在一个元素e’使得e ↦ e’ ⋆ list(e’),这里的e ↦ e’表示e指向e’)。

在你提供的slides中,给出了使用这个归纳谓词的一个证明过程。这个过程就是从列表中取出第一个元素。我们首先定义前提条件{x ≠ 0 ∧ list(x)},然后执行t := *x;,最后得到后置条件{list(t)}。我们可以将归纳谓词展开来证明这个过程,如下:

  1. {x ≠ 0 ∧ (∃e’. x ↦ e’ ⋆ list(e’))} t := *x; {list(t)}
  2. {x ≠ 0 ∧ x ↦ e’ ⋆ list(e’)} t := *x; {list(t)}
  3. {x ≠ 0 ∧ x ↦ e’} t := *x; {x ≠ 0 ∧ x ↦ e’ ∧ t = e’}
  4. {x ≠ 0 ∧ x ↦ e’ ⋆ list(e’)} t := *x; {x ≠ 0 ∧ x ↦ e’ ∧ t = e’ ⋆ list(e’)}

这个过程中,我们在每一步都将归纳谓词进一步展开,直到我们可以清楚地看到在执行t := *x;之后,满足后置条件{list(t)}。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/605470.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

SpringBoot通过加装外部JAR包中的类实现业务插件功能

综合记录一下关于ClassLoader和Spring Bean的动态加载卸载功能 目录 一、需要说明二、总体设计三、具体设计3.1 加载卸载Bean工具类3.2 创建卸载方法3.3 创建加载方法3.4 创建获取具体服务类方法 四、总结 一、需要说明 有一个公共的发送通知的接口,这个接口需要做…

CUDA配置正确,但是torch.cuda.is_available()却是False的解决方案

1.torch.cuda.is_available()返回为False 有时候我们想要使用GPU加速,但是发现CUDA、pytorch都安装好了,且版本也匹配,但是仍然无法使用GPU,显示信息如下: 这时候我们可以看看是不是我们的Pytorch的问题 2.输入下面命令查看pyto…

(学习日记)2023.04.26

写在前面: 由于时间的不足与学习的碎片化,写博客变得有些奢侈。 但是对于记录学习(忘了以后能快速复习)的渴望一天天变得强烈。 既然如此 不如以天为单位,以时间为顺序,仅仅将博客当做一个知识学习的目录&a…

cesium-native编译

我相信点进这个博客的都是一些cesium专业人才,这文章只起了一个抛砖引玉的作用,希望各位人才不惜赐教。 Github地址:CesiumGS/cesium-native (github.com) 编译需求:升级公司的3dtile的架构,提高性能 博客目的&…

(转载)基于混合粒子群算法的TSP问题求解(matlab实现)

1 理论基础 标准粒子群算法通过追随个体极值和群体极值完成极值寻优,虽然操作简单,且能够快速收敛,但是随着迭代次数的不断增加,在种群收敛集中的同时,各粒子也越来越相似,可能在局部最优解周边无法跳出。…

福利·分析

竞争使得生产者剩余和消费者剩余的和最大化 无谓损失指的是由于过量生产或生产不足造成的消费者剩余和生产者剩余的净损失。 税收与补贴的福利分析 从量税效果: 为简单期间,我们对某种商品征收从量税:对每一销售的单元,征收特定…

汽车电子设计之AUTOSAR中CanNM模块

目录 前言 正文 网络节点类型 仅本地唤醒 仅网络唤醒 本地网络唤醒 KL15电唤醒 NM状态机 Bus Sleep Mode Network Mode Prepare Bus-Sleep Mode Passive Mode 状态机时间参数总结 NM状态机切换 网络管理报文结构 NM报文总体结构解析 CBV详解 常用函数接口 前言…

matlab给变量名称

效果 做法: 构建table-> ‘VariableNames’,{‘y’,‘x’} adata; a(:,2)linspace(0.1,4.1,41); tbltable(a(:,1),a(:,2), VariableNames,{y,x});

Verilog学习(SPI协议的Flash驱动控制)

目录 一、SPI通信协议 1.1 SPI物理层 1.2 SPI协议层 二、实战 2.1 SPI控制FLASH实现全擦除代码编写 2.2 上板验证 一、SPI通信协议 1.1 SPI物理层 SPI通信模式为主-从模式 ,分为一主一从、一主多从: 片选线CS用于主机选择对应的从机进行通信&…

html爱情表白神器,回忆纪念册(附源码)

文章目录 1.设计来源1.1 主界面1.2 相关界面 2.效果和源码2.1 动态效果2.2 源代码 源码下载 作者:xcLeigh 文章地址:https://blog.csdn.net/weixin_43151418/article/details/131022313 html爱情表白神器,回忆纪念册 html爱情表白神器&#x…

【JavaEE初阶】万字详解TCP/IP协议!!!(一)

文章目录 1. 应用层和传输层的联系2. UDP协议3. TCP协议3.1 TCP报头介绍3.2 TCP实现可靠传输的核心机制(1)确认应答(2)超时重传(3)连接管理建立连接(三次握手)断开连接(四次挥手) &a…

测试人挣破年入20万的束缚,从第一个python+selenium项目开始!

今天整理一下实战项目的代码共大家学习。(注:项目是针对我们公司内部系统的测试,只能内部网络访问,外部网络无法访问) 问: 1.外部网络无法访问,代码也无法运行,那还看这个项目有啥用 2.如何学…

English Learning - L3 作业打卡 Lesson4 Day28 2023.6.1 周四

English Learning - L3 作业打卡 Lesson4 Day28 2023.6.1 周四 引言🍉句1: Something may appear to be free of charge, but there may be a hidden cost.成分划分弱读连读爆破语调 🍉句2: When we fail to see problems at work, my supervisor tells …

一文了解0欧电阻的奥秘:它不是导线,也不是真的0欧

目录 一、0欧电阻的定义 二、 0欧电阻和导线的区别 三、0欧电阻的选型 四、0欧电阻长什么样 五、0欧姆电阻的用途 1.调试和兼容设计: 2.预留电阻位置: 3.方便布线: 4.方便测试电流: 5.噪声抑制: 6.信号隔离…

学习stm32f103c8t6,如何从正点原子官网下载资料及资料使用

学习stm32f103c8t6,如何从正点原子官网下载资料及资料使用 一、下载资料 用百度搜索“正点原子” 点击进入后找我们需要的芯片型号的资料,选择stm32f103-mini开发板的资料进行下载,其他的像stm32f103的精英版,战舰开发板啥的&am…

代码随想录二刷 day11 | 栈与队列 之 20. 有效的括号 1047. 删除字符串中的所有相邻重复项 150. 逆波兰表达式求值

day11 20. 有效的括号1047. 删除字符串中的所有相邻重复项150. 逆波兰表达式求值 20. 有效的括号 题目链接 解题思路: 有三种不匹配的情况: 第一种情况,字符串里左方向的括号多余了 。 第二种情况,括号没有多余,但是…

大专毕业,从6个月开发转入测试岗位的一些感悟——写在测试岗位3年之际

时光飞逝,我从前端开发岗位转入测试岗位已经三年了,这期间从迷茫到熟悉,到强化,到熟练,到总结,感受还是很深的! 三年前的某一个晚上,我正准备下班回家,我们的项目经理把…

Selenium UI自动化测试入门

1.先下载Pycharm编辑器, 网站:下载地址 2.安装python环境包 地址:Download Python | Python.org 安装的时候记住勾选自动配置环境变量 3.在pycharm中配置python执行器路径 4.安装selenium库 pip install selenium4.1.1 查看当前selenium版…

Flutter架构——线程模型

Flutter的架构分为框架、引擎和嵌入器层(Embedder),其中嵌入器层将Flutter嵌入各个平台。Flutter完整的架构图如下: Flutter中的隔离是通过引擎层的一个线程来实现的,但是Flutter引擎线程的创建与管理又是由嵌入器负责的,也就是说…

Qt个人项目——天气预报,内带QListWidget自定义组件,支持全球城市天气

个人项目,自己制作了一个天气预报,还有选择城市列表,列表分大洲区域选择,具体选择后再进行选择城市,可以更新城市数据,自定义了QListWidget,总体来说完成度比较高,难度也不大&#x…