解析 C++ 源代码并将 in-header 内联方法移动到 .cpp 源文件的工具? [关闭]

Posted

技术标签:

【中文标题】解析 C++ 源代码并将 in-header 内联方法移动到 .cpp 源文件的工具? [关闭]【英文标题】:Tool to parse C++ source and move in-header inline methods to the .cpp source file? [closed] 【发布时间】:2012-01-13 15:00:52 【问题描述】:

我们的应用程序的源代码有几十万行,几千个文件,而且有些地方很老——这个应用程序最初是在 1995 年或 1996 年编写的。在过去的几年里,我的团队大大提高了软件的质量源代码,但还有一个问题特别困扰我:很多类在其头文件中完全定义了很多方法。

在某些情况下,我对在标题中内联声明的方法没有问题 - 结构的构造函数,内联 measurably 使其更快的简单方法(我们有一些这样的数学函数)等。但是无缘无故大量使用内联方法是:

凌乱 很难找到方法的实现(尤其是在类树中搜索虚函数,却发现一个类的版本在标头中声明...) 可能会增加编译后的代码大小 可能会导致我们的链接器出现问题,即notoriously flaky for large codebases。平心而论,在过去的几年里,它变得更好了,但并不完美。

最后一个原因现在可能给我们带来了问题,这是一个很好的理由去检查代码库并将大多数定义移到源文件中。

我们的代码库非常庞大。 是否有自动化工具可以(大部分)为我们完成这项工作?

注意事项:

我们使用Embarcadero RAD Studio 2010。也就是说,C++的方言包括VCL and other extensions等。 一些标头是独立的,但大多数都与相应的 .cpp 文件配对,就像您通常那样。除了扩展名之外,文件名是相同的,即,如果在 X.h 中定义了方法,则可以将它们移动到 X.cpp。这也意味着该工具不必处理整个项目的解析——它可能只解析单独的 .cpp/.h 文件对,忽略包含等,只要它能够可靠地识别定义了主体的方法在类声明中并移动它。

【问题讨论】:

找个实习生来做。 @Zuljin:嗯,可能......但是没有适用的答案! (VS 插件,没有迹象表明他们的网站上有大量更改,所有 cmets 和答案中投票率最高的内容是“哦,你可以轻松创建脚本......”我不认为“容易”和 'parse C++' 通常一起使用!) 您认为 1995 年的代码已经过时了。真可爱:-) @TheBuzzSaw:如果没有非常强大的 C++ 操作技术,让这个想法付诸实施不会很有趣。即使技术很好,也很难做到。 @IraBaxter Nah,你夸大其词了。如果您只想将内联函数从标头移动到 cpp 文件,您只需要一些字符串操作基础知识。您不需要安装整个 LLVM 套件。 【参考方案1】:

你可以试试Lazy C++。我没有使用它,但我相信它是一个命令行工具,可以做你想做的事。

【讨论】:

+1: 不知道这个工具:) +1,以前从未听说过。快速浏览使它看起来像是一个非常有用的工具! 我在阅读FAQ后联系了作者。该工具需要在 .lzz 文件中编写代码,Lazy C++ 将其解析并拆分为 CPP 和 H 文件。我认为将我们的代码组合成单个文件只是为了让一个工具再次拆分它们可能是一样多的工作...... :) 不过感谢您的建议,这是一个有趣的工具。【参考方案2】:

如果代码有效,那么我将投票反对任何重大的自动重写。 修复它可能涉及大量工作。

随着时间的推移进行小的迭代改进是一种更好的技术,因为您将能够单独测试每个更改(并添加单元测试)。无论如何,您对无法找到代码的主要抱怨并不是真正的问题,并且已经解决。已经有工具可以索引您的代码库,因此您的编辑器将跳转到正确的函数定义,而无需您搜索它。查看 ctags 或您的编辑器的等效项。

凌乱

主观的

很难找到方法的实现(尤其是在类树中搜索虚函数,只发现一个类在标题中声明了它的版本......)

已经有工具可用于查找函数。 ctags 将创建一个文件,允许您从任何体面的编辑器 (vim/emacs) 直接跳转到该函数。我相信你的编辑器如果 nto 其中之一有等效的工具。

可能会增加编译后的代码大小

不太可能。编译器将根据内部指标选择是否内联,而不是在源代码中标记为内联。

可能会导致我们的链接器出现问题,这对于大型代码库来说是出了名的不稳定。平心而论,在过去的几年里,它变得更好了,但并不完美。

不太可能。如果您的链接器是易碎的,那么它就是易碎的,它不会对函数的定义产生太大影响,因为这与它们是否被内联无关。

【讨论】:

+1 表示“修复它可能需要做很多工作。”我什至会说“很多工作涉及到修复它。” 谢谢洛基。我不想“重写”——我想保持逻辑代码相同,只需移动它的位置。我知道这不是那么简单,但是...... :) 我预计可能会运行一个工具并手动查看它的更改,尽管它的大小我非常了解代码库,所以我对它的那一面感到非常有信心它。关于其他一些观点,this SO question 可能会让您感兴趣。【参考方案3】:

XE2 包含一个新的静态分析器。试一试新版本的 C++Builer 可能是值得的。

【讨论】:

谢谢大卫!我实际上有一个 C++Builder XE2 Pro 的副本,所以我会尝试使用它。 (尽管工作一直停留在 2010 年 - 我们正在等待 64 位再次升级 - 我尝试保持最新,因此我自己的副本。)我之前只尝试过 2010 年可用的重构,但它们没有'不是很可靠。【参考方案4】:

你有很多问题要解决:

如何理想地重新组合源文件和头文件 如何自动修改代码以执行此操作

在这两种情况下,您都需要一个具有全名解析的强大 C++ 解析器来准确地确定依赖关系。

那么您需要能够可靠地修改 C++ 源代码的机器。

我们的DMS Software Reengineering Toolkit 及其C++ Front End 可用于此目的。 DMS 已用于大规模 C++ 代码重构;请参阅http://www.semdesigns.com/Company/Publications/ 并追踪第一篇论文“案例研究:通过自动程序转换重新设计 C++ 组件模型”。 (您可以从那里下载这篇论文的旧版本,但发表的版本更好)。 AFAIK,DMS 是唯一被用于大规模转换 C++ 的工具。

这个SO discussion on reorganizing code直接解决了分组问题。

【讨论】:

以上是关于解析 C++ 源代码并将 in-header 内联方法移动到 .cpp 源文件的工具? [关闭]的主要内容,如果未能解决你的问题,请参考以下文章

使用 C++ 中的内联汇编对缓冲区中的数字求和

关于C++内联函数

为啥 C++ 中的 main() 不能内联?

在 Python 2.7 中编织内联 C++ 代码

用于在 C++ 中管理平台特定代码的内联命名空间技术

C++ 重构内联 Double 以获得更快的代码 PolyBelp