frama-c slicing插件似乎会丢弃使用过的堆栈值。

问题描述 投票:2回答:1

问题描述

我正在开发一个frama-c插件,使用slicing插件作为库来删除自动生成的代码中未使用的部分。不幸的是,slicing插件丢弃了一堆堆栈值,而这些堆栈值实际上是被使用的。它们被使用的原因是它们的地址包含在结构中,而这些结构被交给了抽象的外部函数。

简单的例子

这是一个更简单的例子,它的模型与我的一般结构相同。

/* Abstract external function */
void some_function(int* ints[]);

int main() {
  int i;
  int *p = &i;
  int *a[] = { &p };
  some_function(a);
  return 0;
}

当用 frama-c-gui -slice-calls some_function experiment_slicing.c (我还不知道如何在没有gui的情况下调用命令行时看到切片输出)除了声明之外,它放弃了所有的东西。int *a[]; 和呼吁 some_function.

试图修复的问题

我试着通过添加ACSL注释来解决这个问题.然而我认为是合理的规范(见下文)并没有发挥作用。

/*@ requires \valid(ints) && \valid(ints[0]);
 */
void some_function(int* ints[]);

然后我尝试了一个assign(见下图),它确实具有所需的行为。然而这并不是一个正确的规范,因为函数实际上从未向指针写入,而是需要读取它以实现正确的功能。我担心如果我继续使用这样一个不正确的规范,会导致以后出现奇怪的问题。

/*@ requires \valid(ints) && \valid(ints[0]);
   assigns  *ints;
*/
void some_function(int* ints[]);
c frama-c program-slicing acsl
1个回答
1
投票

你的方向是对的:是这个问题。assigns 子句,你应该在这里使用:它将指出对未定义函数的调用涉及到内存状态的哪些部分。然而,您需要提供一个完整的 assigns 句,以及其 \from 部分(表示读取哪个内存位置以计算写入的内存位置的新值)。

我已经添加了一个 int 变量,因为你的函数并没有返回一个结果(void return type).对于返回东西的函数,你也应该有一个子句。对于一个要返回东西的函数,你还应该有一个子句 assigns \result \from ...;:

int x;

/*@ assigns x \from indirect:ints[..], *(ints[..]); */
void some_function(int* ints[]);

int main() {
  int i;
  int*p = &i;
  int *a[] = { &p };
  some_function(a);
  return 0;
}

负责人: 负责人: 负责人: 负责人: 负责人: 负责人: 负责人: 负责人: 负责人: 负责人: 负责人: 负责人: 负责人: 负责人: 负责人: 负责人: 负责人: 负责人: 负责人: 负责人: 负责人: 负责人: 负责人: 负责人: 负责人: 负责人: 负责人: 负责人: 负责人: 负责人: 负责人: 负责人: 负责人: 负责人: 负责人: 负责人: 负责人: 负责人: 负责人: 负责人: 负责人: 负责人: 负责人: 负责人: 负责人: 负责人: 负责人: 负责人: 负责人: 负责人: 负责人: 负责人: 负责人: 负责人: 负责人: 负责人: 负责人: 负责人: 负责人: 负责人: 负责人: 负责人: 负责人: 负责人: 负责人: 负责人: 负责人: 负责人: 负责人: 负责人: 负责人: 负责人: 负责人: 负责人: 负责人: 负责人: 负责人: 负责人: 负责人: 负责人: assigns 子句表示 some_function 可能会改变 x中存储的地址计算出新的值。ints[..](该 indirect 标签告诉我们,我们并没有直接使用它们的值,这一点将在8.2节的 Eva的手册),以及它们的内容。

使用 frama-c -slice-calls some_function file.c -then-last -print (最后一个参数是用来在标准输出上打印结果的文件。-then-last 表示以下选项应在最后创建的Frama-C项目上操作,在这种情况下,就是切片后的项目,以及 -print 打印该工程的C代码。你也可以使用 -ocode output.c 以将代码的漂亮打印重定向至 output.c...)给出了以下结果。

* Generated by Frama-C */
void some_function(int **ints);

void main(void)
{
  int i;
  int *p = & i;
  int *a[1] = {(int *)(& p)};
  some_function(a);
  return;
}

另外,请注意你的例子没有很好的类型。&p 是一个指向int的指针, 因此应该存储在... int** 数组,而非 int* 数组。但我认为这只是源于减少你原来的例子,对于切片本身并没有太大的影响。

© www.soinside.com 2019 - 2024. All rights reserved.