我们如何检测源代码中的所有指针比较? C ++

时间:2016-08-18 08:23:03

标签: c++ code-analysis static-code-analysis cqlinq cppdepend

我们希望从类类型中找到所有指针比较。例如,我们有一个A类,派生类来自A,如B,C等。

A *pa;
A *pa2;
B *pb;

必须在我们的源代码中找到if(pa == pa2)或if(pa!= pb)等所有比较。

我知道我们可以使用CLang分析器来查找这些比较,但我们的源代码与CLang不兼容。我们正在使用visual studio 2015。

请不要给出类似的解决方案;从源代码中删除A类然后尝试编译它,以便从A类中找到它没有编译的所有用法。

有人找到解决方案吗?像CppCheck(检查可能的错误)或Visual Studio扩展的工具?

编辑:

有谁知道,我怎么能用CppDepend / CQLinq语法找到我的代码中的所有比较?它也可以帮助我。 CppDepend使用CLang,但如果它有解析错误,它会继续解析。

3 个答案:

答案 0 :(得分:2)

我们的DMS Software Reengineering Toolkit及其C++14 front end可用于执行此操作。

DMS是通用程序分析和转换机器,可以进行定制以实现对作为插件模块提供给它的编程语言的期望效果。它的C ++ 14前端可配置处理纯ANSI,GCC / Clang样式语法或Visual Studio语法。它包括一个完整的预处理器。

为了实现OP的目的,可以将DMS配置为:

  1. 解析生成AST的编译单元。
  2. 对于每个编译单元,执行名称和类型解析。这将构建包含类型信息的符号表,并提供基础 用于计算任意表达式的类型。这个能力是 内置于DMS的C ++前端。
  3. 抓取AST,寻找运营商==和!=
  4. 要求DMS计算右侧和左侧子表达式的类型
  5. 验证类型是目标类,还是从目标类继承的类。 (据推测,目标类被识别为在某个源文件/行位置定义;这可以通过搜索符号表来找到。检查类型是否来自另一个只是递归搜索记录的可能的多个父链接对于符号表链接,检查父项是否是所需的目标类型。)
  6. 报告运营商的文件名,来源行和列。
  7. 上述每个步骤都由DMS和C ++ 14前端提供的机器/ API直接支持。这可能需要将几页自定义代码添加到DMS中才能达到效果。

答案 1 :(得分:0)

我的解决方案是:(正如@MM所说)用模板包装类包装指针,它实现像-> *这样的运算符重载(因此编译问题较少)并删除比较运算符,如== !=(所以查找与编译错误的比较)。可以使用正则表达式替换所有指针。 (A *A_Wrapper

我还发现,在地图中使用指针就像指针比较。如果在地图中使用指针,则还应删除包装类中的< - 运算符。

当然,我有编译错误,但这些错误并不难解决。似乎这是一定的解决方案。

我希望能帮助别人。

答案 2 :(得分:-2)

我猜我错过了这个问题。所以你只想找到指向类型A,B,C等的任何指针的所有实例,其中指针通过比较在条件表达式中使用...

所以你知道所有的类型名称。这意味着存在有限数量的类型和有限数量的比较,例如==!=&lt; =&gt; =&lt; &GT;正确?

因此,对于所有类型创建的指针的每个实例,都要构建一个表。这将为您提供您要查找的每个指针的编码名称。

fred * myfred,* yourfred,* thefred;

account * primaryacct,* secondacct; ......等等......

你的桌子是:
myfred
yourfred
thefred
primaryacct
secondacct

现在每个实例都有一个 - 从第一个'myfred'开始,找到myfred,然后是==然后通过!=等等(吸收任何空格),当你找到第一个(comaprison的左侧,例如< / p>

secondacct&lt; =

然后得到右侧)并将其与您构建的表中的每个指针编码名称进行比较。当你有像myfred!= primaryacct这样的比赛时,你可以用它做你喜欢的事。我们只是为了论证,你想要执行全局搜索并替换给定的比较或比较列表,你可以通过打开一个额外的输出文件来实现这一点,当你读入并找到每个您可以将它输出到新的源代码文件中。

基本上只需查找每个比较,查看它的每一面,看看双方是否都有一个表格中的编码名称。本质上,您只是在有限的比较字符串组合的两侧使用相同的标识符表来解析代码 - 同样它们是:[==!=&lt; =&gt; =&lt; &GT; ]

我不知道这样做的软件工具,但你可以很快地编写代码。它当然只能用于这一目的,但它可以快速完成工作。

我当然假设您的源代码是文本形式,并且您可以打开文件并将其读入以执行此操作。如果是这样,那么你可以得到你想要的结果,例如每个文件和行的列表,找到每个表达比较的匹配项。

在阅读时获取整行代码 -

在C中 - 只需使用fgets

在C ++中 - 使用getline

然后使用上述逻辑解析您读入的缓冲区。

--------------已编辑---------------关于以下评论

@YusufRamazanKaragöz - Oak - 我为过度概括而道歉。您是否有可能提供包含其中一些问题的代码示例 - 例如,如果它涵盖多行?我的思考过程基于你写的“所有比较,如if(pa == pa2)或if(pa!= pb)必须在我们的源代码中找到”,仅此而已,我没有扩展到函数返回,至于构建表 - 你知道类型是否正确?因此,对于具有声明这些类型的变量的每一行,都是如何构建它的。例如,如果我想在程序的所有文件的每行代码中都有一个每个char定义变量的表 - 我会在所有行中搜索单词char。然后在那行之后我会寻找逗号分隔的字符串,直到没有逗号或分号(可以继续到下一行,所以使用fgetc代替fgets)。其中一些声明是完全的,有些可能是* char,有些是char [] - 等等。然后我会得到char类型的每个变量的列表。我的意思是,如果你在搜索你正在谈论的类型名称时,你不能看到它出现的那一行,以及之后宣布的一切吗?如果可以,那么您可以构建索引表。还是有一些原因我不明白为什么不能这样做?查找已转换的值会创建另一组解析规则,并且会使模板与对象比较进一步使任务复杂化。直到现在,我才真正理解你从原始问题中解决的困境。我真的很想提供帮助,但也许一段涵盖每种解析范例的代码都可以帮助我确定是否可以。实际上,如果你能给我一个关于你为什么要这样做的想法会让我有一个更好的思考过程。你想全球改变什么吗?如果你觉得这种努力是徒劳的,我当然会顺从你的决定并停止尝试。感谢您耐心等待时间,我希望您找到解决方案。