Warm tip: This article is reproduced from serverfault.com, please click

c-如何获得使用递归的警告?

(c - How to get a warning for using recursion?)

发布于 2017-07-19 15:08:03

嵌入式软件开发的某些规则集和准则完全禁止递归。arm-none-eabi-gcc与基于ARM Cortex-M4的微控制器一起使用。

我正在寻找一个静态分析工具,该工具会警告我有关代码中递归的使用。我对此类工具的经验很少。是否可以为此使用clang-tidy或clang静态分析器?如果是,我如何配置它们以警告递归?

(快速浏览一下gcc选项摘要告诉我,仅gcc不能做到这一点。)

笔记:

  • 请不要告诉我“只是不递归”代码库很大,而且不是我一个人的。我希望能够证明其中没有递归。
    (这就像说“只是不要取消引用空指针”。虽然没有人故意这样做,但是出于某种原因存在工具来验证它不会发生。)
Questioner
Venemo
Viewed
0
Some Who Call Me Tim 2017-07-20 12:54:59

使用Clang生成的调用图数据可以解决此问题。

步骤1.使用clang生成调用图信息:

clang -S -emit-llvm SourceFile.c -o - | opt -analyze -print-callgraph 

(从生成C ++代码的调用图,替换-dot-callgraph-print-callgraph。)

对于像这样的输入:

void a(){}
void b(){a();}
void c(){a(); b();}
void d(){a(); c();}
void e(){e();}

这将产生:

CallGraph Root is: <<null function: 0x0x7fdef25036c0>>
Call graph node <<null function>><<0x7fdef25036c0>>  #uses=0
  CS<0x0> calls function 'a'
  CS<0x0> calls function 'b'
  CS<0x0> calls function 'c'
  CS<0x0> calls function 'd'

Call graph node for function: 'a'<<0x7fdef2503750>>  #uses=4

Call graph node for function: 'b'<<0x7fdef25037d0>>  #uses=2
  CS<0x7fdef2500a38> calls function 'a'

Call graph node for function: 'c'<<0x7fdef2503870>>  #uses=2
  CS<0x7fdef2500cb8> calls function 'a'
  CS<0x7fdef2500d28> calls function 'b'

Call graph node for function: 'd'<<0x7fdef2503970>>  #uses=1
  CS<0x7fdef2500fe8> calls function 'a'
  CS<0x7fdef2501058> calls function 'c'

Call graph node for function: 'e'<<0x7f8912d03c10>>  #uses=2
  CS<0x7f8912d01318> calls function 'e'

(在C ++中,错误的函数名称可以用清理c++filt;模板很难使用,但可以使用。)使用这些数据,可以勾勒出如何检测递归:

步骤2.将调用图数据解析为常用的脚本语言,以形成调用图的表示形式。

class Graph(object):

  _callees = []

  def add_callee(self, f):
    self._callees.append(f)
    # etc

步骤3.对于每个功能,通过步行图查找对该功能的调用。像这样的东西:

def walkGraph(node,f,stack):
  for callee in node._callees:
    if f == callee:
      print('Recursion!')
      dumpStack(stack,f)
    else:
      walkGraph(callee,f,stack.append(node))