如何检查给定文件是否存在依赖性错误?
How do I check whether given files have dependency bugs?
我是 C++ 的新手,被分配了以下作业:
鉴于我有以下文件集:alpha.cpp、bravo.cpp 和 charlie.cpp,我应该创建一个程序来检查这些文件是否具有依赖性漏洞。
我的想法是让程序读取文件,创建一个邻接列表图,将每个文件作为一个顶点,如果一个 .cpp 文件包含另一个 .cpp 文件,则有向边从一个节点到另一个节点。所以总的来说,我需要 运行 在图上进行深度优先搜索,看看图是否有后边。
那是正确的轨道吗?我觉得我明白我应该做什么,但我不确定如何准确地实施它。
我会使用您的构建系统并使用一点解析魔法。我有一个用于很多项目的 Makefile here。它解析出包含并为它们生成目标。
像 Make 这样的工具的问题是它们必须为您进行图形遍历。他们通过获取所有部分排序(依赖声明),并对它进行拓扑排序以获得完整排序(文件的线性化,以便如果 A 依赖于 B,则 B 在 A 之前)来做到这一点。
但是,关于拓扑排序的事情是它只存在于直接 非循环 图。因此,如果您生成像 Makefile 这样的依赖项,并且存在任何循环,构建将失败,这正是您想要的,因为当您尝试递归包含内容时,它无论如何都会发生。
如果您正在寻找查看依赖关系的工具,我会考虑使用:
makedepend
或 g++ -MD
(或 clang++ -MD
)用于生成 #include
依赖项。然后构建一个图来检测循环。
g++ -c
和 nm
(-U
和 --defined-only
)读取目标文件中定义和需要的符号。您甚至可以只比较已定义和已声明符号的列表(包括在某处定义的符号,例如 /usr/lib64/libstdc++.so.6
),看看是否有缺失的符号。
顺便说一句:根据您问题中的评论,"dependency bug" 的定义不是很有用。一般来说,a.h
包括 b.h
包括 a.h
不一定是任何类型的错误。如果包含它们的文件可以编译,那么显然您拥有有效的 C++。所以,不是错误。出现以下情况:
给定的依赖循环可能是不必要的:一些 b.h
可能不需要包含 a.h
。编译成功。
一个给定的依赖循环可能是必要的,但有效:一些 b.h
可能需要来自 a.h
的内容,它可能会提供一些东西返回给 a.h
,但是 include 语句和依赖项是有序的,这样它就可以工作。编译成功。
给定的依赖循环可能是必需的,但无效:不可能满足所述的依赖关系。编译失败。
检测#3,只需要编译文件即可,如果编译失败,可能是依赖bug。
a.h
和 b.h
中的 declarations/definitions 和 include 语句可能会重新排序,将 #3 转换为 #2。
#2 和#1 不一定是错误,但您必须完全解析文件才能确定是这种情况。
当然您可以简单地声明这些循环在您的项目中是不允许的。所以它们违反了您的项目规则,也许这让您可以称它们为错误 :)
我是 C++ 的新手,被分配了以下作业:
鉴于我有以下文件集:alpha.cpp、bravo.cpp 和 charlie.cpp,我应该创建一个程序来检查这些文件是否具有依赖性漏洞。
我的想法是让程序读取文件,创建一个邻接列表图,将每个文件作为一个顶点,如果一个 .cpp 文件包含另一个 .cpp 文件,则有向边从一个节点到另一个节点。所以总的来说,我需要 运行 在图上进行深度优先搜索,看看图是否有后边。
那是正确的轨道吗?我觉得我明白我应该做什么,但我不确定如何准确地实施它。
我会使用您的构建系统并使用一点解析魔法。我有一个用于很多项目的 Makefile here。它解析出包含并为它们生成目标。
像 Make 这样的工具的问题是它们必须为您进行图形遍历。他们通过获取所有部分排序(依赖声明),并对它进行拓扑排序以获得完整排序(文件的线性化,以便如果 A 依赖于 B,则 B 在 A 之前)来做到这一点。
但是,关于拓扑排序的事情是它只存在于直接 非循环 图。因此,如果您生成像 Makefile 这样的依赖项,并且存在任何循环,构建将失败,这正是您想要的,因为当您尝试递归包含内容时,它无论如何都会发生。
如果您正在寻找查看依赖关系的工具,我会考虑使用:
makedepend
或g++ -MD
(或clang++ -MD
)用于生成#include
依赖项。然后构建一个图来检测循环。g++ -c
和nm
(-U
和--defined-only
)读取目标文件中定义和需要的符号。您甚至可以只比较已定义和已声明符号的列表(包括在某处定义的符号,例如/usr/lib64/libstdc++.so.6
),看看是否有缺失的符号。
顺便说一句:根据您问题中的评论,"dependency bug" 的定义不是很有用。一般来说,a.h
包括 b.h
包括 a.h
不一定是任何类型的错误。如果包含它们的文件可以编译,那么显然您拥有有效的 C++。所以,不是错误。出现以下情况:
给定的依赖循环可能是不必要的:一些
b.h
可能不需要包含a.h
。编译成功。一个给定的依赖循环可能是必要的,但有效:一些
b.h
可能需要来自a.h
的内容,它可能会提供一些东西返回给a.h
,但是 include 语句和依赖项是有序的,这样它就可以工作。编译成功。给定的依赖循环可能是必需的,但无效:不可能满足所述的依赖关系。编译失败。
检测#3,只需要编译文件即可,如果编译失败,可能是依赖bug。
a.h
和 b.h
中的 declarations/definitions 和 include 语句可能会重新排序,将 #3 转换为 #2。
#2 和#1 不一定是错误,但您必须完全解析文件才能确定是这种情况。
当然您可以简单地声明这些循环在您的项目中是不允许的。所以它们违反了您的项目规则,也许这让您可以称它们为错误 :)