- android - 多次调用 OnPrimaryClipChangedListener
- android - 无法更新 RecyclerView 中的 TextView 字段
- android.database.CursorIndexOutOfBoundsException : Index 0 requested, 光标大小为 0
- android - 使用 AppCompat 时,我们是否需要明确指定其 UI 组件(Spinner、EditText)颜色
我有我的测试代码(研究WP循环不变量),它将两个长整数与数组单元格中每个数字的表示相加:
int main(int argc, const char * argv[]) {
char a[32], b[32];//size can be very big
memset(a, 0, sizeof(a));
memset(b, 0, sizeof(b));
scanf("%s %s", a, b);
unsigned int size1 = strlen(a);
unsigned int size2 = strlen(b);
//code to reverse a string. currently proved
reverse(a, size1);
reverse(b, size2);
for (unsigned int i = 0; i < size1; i++) a[i]-='0'; //move from chars to integers
for (unsigned int j = 0; j < size2; j++) b[j]-='0';
unsigned int maxsize = size1;
if (size2 > maxsize) maxsize = size2;
int over = 0;
//actual computation code
/*@
loop invariant maxsize == \max(size1, size2);
loop invariant bound: 0 <= k <= maxsize;
loop invariant ov: \forall integer i; 0 < i < k ==> \at(a[i], Here) == (\at(a[i], Pre) + b[i]+ Over((char *)a, (char *)b, i)) % 10;
loop assigns k, a[0..maxsize-1],over;
loop variant maxsize - k;
*/
for (unsigned int k = 0; k < maxsize; k++)
{
char sum=a[k] + b[k] + over;
//over=overflow is for 9+9 = 18, result=8, over=1
a[k] = sum % 10;
over = sum / 10;
}
if (over != 0) a[maxsize++] = over;
//...
return 0;
}
/*@
@predicate
Unchanged{K,L}(char* a, integer first, integer last) = \forall integer i; first <= i < last ==> \at(a[i],K) == \at(a[i],L);
axiomatic ReminderAxiomatic
{
logic integer Reminder {l} (integer x, integer y);
axiom ReminderEmpty: \forall integer x, integer y; x < y ==> Reminder(x, y) == x;
axiom ReminderNext: \forall integer x, integer y; x>=y ==> Reminder(x, y) == Reminder(x-y, y)+0;
}
axiomatic DivAxiomatic
{
logic integer Div {l} (integer x, integer y);
axiom DivEmpty: \forall integer x, integer y; x < y ==> Div(x, y) == 0 ;
axiom DivNext: \forall integer x, integer y; x >= y ==> Div(x, y) == Div(x - y, y) + 1 ;
}
axiomatic OverAxiomatic
{
logic integer Over {L}(char *a, char * b, integer step) reads a[0..step-1], b[0..step-1];
axiom OverEmpty: \forall char *a, char * b, integer step; step <= 0 ==> Over(a, b, step) == 0;
axiom OverNext: \forall char *a, char * b, integer step; step > 0 && a[step-1]<10 && a[step-1]>=0 && b[step-1]<10 && b[step-1]>=0
==> Over(a, b, step) == Div((int) a[step-1]+(int)b[step-1]+(int)Over(a,b,step-1), 10);
}
*/
/*@
requires 0 <= maxsize < 10;
requires \valid (a+(0..maxsize-1));
requires \valid (b+(0..maxsize-1));
requires \valid (res+(0..maxsize));
requires \forall integer i; 0 <= i < maxsize ==> 0 <= (int)a[i] < 10;
requires \forall integer i; 0 <= i < maxsize ==> 0 <= (int)b[i] < 10;
*/
void summ(char *a, char *b, char *res, unsigned int maxsize) {
char over = 0;
/*@
loop invariant bound: 0 <= k <=maxsize;
loop invariant step: \forall integer i; 0 <= i < k ==> res[i] == (char) Reminder((int)a[i]+ (int)b[i]+ (int)Over((char *)a, (char *)b, i) , 10);
loop invariant unch: Unchanged{Here,LoopEntry}((char *)res, k, maxsize);
loop assigns k, over, res[0..maxsize-1];
loop variant maxsize-k;
*/
for (unsigned int k = 0; k < maxsize; k++)
{
char sum = a[k] + b[k] + over;
res[k] = sum % 10;
over = sum / 10;
}
//
if (over != 0) res[maxsize++] = over;
}
最佳答案
首先,如果您的问题包含一个MCVE,在本例中包括您当前正在处理的C函数(而不仅仅是它的主体)和您编写的ACSL注释,它们在代码中的确切位置会更好。用于启动Frama-C的命令行也不会受到影响,同时也不会影响您遇到问题的注释列表。
除此之外,这里还有一些可能与您的问题有关的事情(同样,如果没有准确的描述,很难确定)。loop assigns
是错误的:您在循环中分配了over
,但这里没有提到它。
我不确定WP是否支持\max
。
模除法和整数除法是自动校准器经常遇到的两种运算您可能需要一些额外的断言和/或公理来帮助它们。
你的loop invariant
没有提到a[i]
的值由于k <= i< maxsize
表示loop assigns
的所有细胞都可能已被修改,您必须添加一个不变量,告诉具有更高索引的细胞到目前为止尚未被触摸。
我不完全确定您使用的a
:\at(a[i],Pre)
表示当前函数的开始因此,如果Pre
和scanf
与循环处于相同的函数中(同样,MCVE会澄清这一点),则这不是真的您可能想谈论reverse
来引用第一次进入循环的状态下的单元格值。
更新
恐怕WP无法完全证明您的注释,但我设法获得了一个版本,其中只有一个\at(a[i],Loop_entry)
,基本上是lemma
函数的reads
子句的扩展版本未经验证(我相信在WP的实际C内存表示下无法证明)请注意,这意味着要玩WP的提示功能下面提供了代码和脚本,但我将从评论您的原始版本开始:
不需要Over
和Div
如果有什么问题,他们会把证明人弄糊涂的。你可以坚持使用Reminder
和xxx/10
实际上,我对除法和模的评论有点过于谨慎。在目前的情况下,在这个水平上一切似乎都很好。
类似地,xxx%10
可以是内联的,但是保持这种方式应该不会有什么坏处。
我使用了Unchanged
而不是unsigned char
,因为它避免了由于整数提升而产生的一些虚假转换,并且删除了逻辑中的任何转换通常,您不必在ACSL注释中引入这种类型转换,除非可能是为了指示某些计算保持在适当的范围内(如char
)。这样的强制转换被转换为证明义务中的函数调用,而且它可能再次混淆证明者。
缺少一个不变量,表示\let x = y + z; x == (int) x;
确实包含上一步的潜在进位(同样,缺少不变量的一个好提示是over
中提到的位置不会出现在任何loop assigns
中)。
最后,还有一个小的微妙之处:如果您不以某种方式指出loop invariant
只能是over
或0
,则没有任何东西可以阻止加法溢出1
(这使得无法证明具有unsigned char
的C计算及其具有无限整数的ACSL对应项给出相同的结果)。由于unsigned char
函数的递归性质,这可以通过所谓的引理函数来建立,在引理函数中,数学归纳是通过一个带有适当不变量的简单for循环来实现的
此外,我还作为不变量明确地添加了Over
和a
保持不变这通常是由b
暗示的,但是有了这些明确的假设,在脚本中就更容易了。
总而言之,这里是最后的代码:
/*@
axiomatic Carry {
logic integer Over {L}(unsigned char* a, unsigned char* b, integer step)
reads a[0 .. step - 1], b[0 .. step - 1];
axiom null_step: \forall unsigned char* a, *b, integer step;
step <= 0 ==> Over(a,b,step) == 0;
axiom prev_step: \forall unsigned char* a, *b, integer step;
step > 0 ==>
Over(a,b,step) ==
(a[step-1] + b[step - 1] + Over(a,b,step-1)) / 10;
lemma OverFootPrint{L1,L2}:
\forall unsigned char* a, unsigned char*b, integer step;
(\forall integer i; 0<=i<step ==> \at(a[i],L1) == \at(a[i],L2)) &&
(\forall integer i; 0<=i<step ==> \at(b[i],L1) == \at(b[i],L2)) ==>
Over{L1}(a,b,step) == Over{L2}(a,b,step);
}
*/
/*@
requires \valid(a+(0 .. step-1));
requires \valid(b+(0 .. step - 1));
requires \forall integer i; 0<=i<step ==> 0<=a[i]<10 && 0<=b[i]<10;
assigns \nothing;
ensures 0<= Over(a,b,step) <= 1;
*/
void lemma_function(unsigned char* a, unsigned char* b, unsigned int step) {
/*@
loop invariant 0<=i<=step;
loop invariant \forall integer k; 0<=k<=i ==> 0 <= Over(a, b, k) <= 1;
loop assigns i;
*/
for (int i = 0; i < step; i++);
}
/*@
requires 0 <= maxsize < 10;
requires \valid (a+(0..maxsize-1));
requires \valid (b+(0..maxsize-1));
requires \valid (res+(0..maxsize));
requires \separated (a+(0..maxsize-1),res+(0..maxsize));
requires \separated (b+(0..maxsize-1),res+(0..maxsize));
requires \forall integer i; 0 <= i < maxsize ==> 0 <= a[i] < 10;
requires \forall integer i; 0 <= i < maxsize ==> 0 <= b[i] < 10;
*/
void summ(unsigned char* a, unsigned char*b, unsigned char* res,
unsigned int maxsize) {
unsigned char over = 0;
/*@
loop invariant bound: 0 <= k <=maxsize;
loop invariant step: \forall integer i; 0 <= i < k ==> res[i] == (a[i]+ b[i]+ Over(a,b,i)) % 10;
loop invariant over: over == Over(a,b,k);
loop invariant a_unchanged: \forall integer i; 0 <= i < maxsize ==>
\at(a[i],LoopEntry) == a[i];
loop invariant b_unchanged: \forall integer i; 0 <= i < maxsize ==>
\at(b[i],LoopEntry) == b[i];
loop invariant unch: \forall integer i; k<=i<=maxsize ==> \at(res[i],LoopEntry) == res[i];
loop assigns k, over, res[0..maxsize-1];
loop variant maxsize-k;
*/
for (unsigned int k = 0; k < maxsize; k++)
{
unsigned char sum = a[k] + b[k] + over;
res[k] = sum % 10;
over = sum / 10;
lemma_function(a,b,k);
}
//
if (over != 0) res[maxsize++] = over;
}
loop assigns
中(例如
scripts/typed
),然后使用以下命令行:
frama-c[-gui] -wp -wp-prover alt-ergo,script -wp-session scripts file.c
file.c
目录的名称(它必须与
scripts
的参数匹配),但是
-wp-session
和脚本的文件名必须与给定的一样,因为WP将使用它们来检测它们应该证明的证明义务。在GUI模式下,您可以查看脚本,但可能很难理解和解释每个步骤不符合SO的答案。
关于c - 如何在frama-c wp中用计算证明迭代循环?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45915333/
我正在尝试在我正在处理的博客上使用类别帖子 (WP-CPL) 插件来按类别过滤“最近的帖子”。基本上,当有人点击博客上的类别名称时,我希望它显示该类别的帖子。这将通过 Life Is Simple 模
我的形象 我只想为某些用户隐藏特定页面。 function remove_menus(){ // get current login user's role $roles = wp_g
我的形象 我只想为某些用户隐藏特定页面。 function remove_menus(){ // get current login user's role $roles = wp_g
我为我的 wp 网站创建了一个简单的脚本,我正在尝试从 2 个表的 wp 数据库中获取正确的数据,这是代码, 当我显示“user_ref_id”列的结果重复多次时,这是代码 global $wpdb;
我安装了一个名为 Hide My WP 的插件来更改网站结构,但考虑到我使用的是自定义主题,它破坏了一些功能。所以我手动从plugins文件夹中删除了插件,但是从那以后我就无法访问/wp-admin/
我试图从头开始创建 WXR 文件(WordPress eXtended Rss)。 我的代码基于 XML/ wordpress生成的WXR文件并像这样开始: 我是这样开始的: $newxml =
我想将所有页面重定向到 http://www.expample2.com除了 wp-admin 和 wp-json。 例如,用户能够登录 http://www.example1.com/wp-admi
我使用 MAMP 在本地构建了一个快速的 WordPress 网站,然后将其 checkin SVN 存储库。然后我将其检查到我的开发服务器上。 除了运行 search and replace too
在搜索端点的 WP REST API (wp json) 中: https://www.example.com/wp-json/wp/v2/search?search=searchPhrase&_em
我正在使用这个 NGINX 规则来强制 WordPress 网站的尾部斜杠: rewrite ^([^.]*[^/])$ $1/ permanent; 但是这个规则给 Gutenberg 和 wp-j
在搜索端点的 WP REST API (wp json) 中: https://www.example.com/wp-json/wp/v2/search?search=searchPhrase&_em
我正在使用这个 NGINX 规则来强制 WordPress 网站的尾部斜杠: rewrite ^([^.]*[^/])$ $1/ permanent; 但是这个规则给 Gutenberg 和 wp-j
我想限制所有用户访问 WordPress 网站登录。 例如:假设我有 WordPress 网站域 example1.com,我想限制所有用户使用 example1.com/wp- 访问管理员登录adm
尝试实现这里讨论的技术, http://z9.io/2013/10/21/shiny-new-dynamic-content-wp-super-cache/ 进入使用 Genesis 框架的站点。我想
我试图在位于我的 WP 主题文件夹内的 PHP 文件中调用自定义 AJAX 函数,但是我无法让它检索输出。我认为问题在于将 WP 查询链接到主 WP 文件? $.ajax({ url: "../../
我正在编写一个 perl 脚本,用于将 Wordpress 安装从一个地方迁移到另一个地方。在这项工作中,我需要使用 wp-cli 调用从 wp-config 文件中获取 wordpress 数据库名
我最近更改了我的 WordPress 网站上的目录。我导出了数据库,搜索并替换了旧 URL 为新 URL,然后重新导入。该网站的前端工作正常,但任何页面的后端都需要近 15 秒才能加载。 从funct
我使用下面的代码通过类似的单词标签获取帖子但不起作用 $query = " SELECT * FROM $wpdb->posts , $wpdb->terms
我已经通过 DirectAdmin 在我的服务器上安装了 SSL 证书。这似乎运作良好。 我已将 wp_*_options 表中的 url 更改为 https://mydomain.nl 等。突然我的
我正在建立一个网站,使用 wordpress+buddypress(最新版本)。 在这个网站中,我有自己的自定义登录|注册|重置密码表单,我不想将它们链接到后端 wp-forms。 我已经阻止了所有用
我是一名优秀的程序员,十分优秀!