I use the Frama-C tool to generate the dependence graph of this program(main.c).
#include<stdio.h>
int main()
{
int n,i,m,j;
while(scanf("%d",&n)!=EOF)
{
m=n;
for(i=n-1;i>=1;i--)
{
m=m*i;
while(m%10==0)
{
m=m/10;
}
m=m%10000;
}
m=m%10;
printf("%5d -> %d\n",n,m);
}
return 0;
}
The command is:
frama-c -pdg -dot-pdg main main.c
dot -Tpdf main.main.dot -o main.pdf
The result is

My question is why the statments “m=m*i;”,”m=m%10000” do not map to nodes. The result does not seem right,because there are three loops in the code.
A slicer for C programs only works in practice if its defined goal is
to preserve defined executions, and the slicer is allowed to change undefined executions.
Otherwise, the slicer would be unable to remove a statement such as
x = *p;as soon as it is unable to determine thatpis a valid pointer at that point, even if it knows that it does not needx, just because if the statement is removed, executions wherepis NULL at that point are changed.Frama-C does not handle complex library functions such as
scanf(). Because of this, it thinks that local variablenis used without being initialized.Type
frama-c -val main.cYou should get a warning like:
The word
assertmeans that Frama-C’s option-valis unable to determine that all executions are defined, and “NON TERMINATING FUNCTION” means that it is unable to find a single defined execution of the program to continue from.The undefined use of an uninitialized variable is the reason the PDG removes most statements. The PDG algorithm thinks it can remove them because they come after what it thinks is an undefined behavior, the first access to variable
n.I modified your program slightly to replace the
scanf()call with a simpler statement:and I got the PDG below. It looks complete as far as I can tell. If you know better layout programs than
dotbut that accept thedotformat, this is a good chance to use them.Note that the condition of the outmost
whilebecametmp != -1. The nodes of the graph are the statements of an internal normalized representation of the program. The conditiontmp != -1has a data dependency to the node for the statementtmp = unknown_int();. You can display the internal representation withframa-c -print main.c, and it will show that the outmost loop condition has been broken into:This helps, among other things, the slicing to remove only the parts of a complex statement that can be removed instead of having to keep the entire complex statement.