【问题标题】:Incorrect circular reference error不正确的循环引用错误
【发布时间】:2009-05-24 14:31:11
【问题描述】:

我们的团队已经使用 Delphi 6 多年,然后在 2006 年前切换到 Delphi。对于这两个版本,我们都有以下问题:编译器经常抱怨一个应该递归使用的单元。该单元是一个 40k LOC 单元,是一个拥有近 100 万 LOC(包括第三方)的项目的核心。

错误消息不正确:项目的完整构建始终有效。不幸的是,错误消息没有告诉我们假定的循环引用在哪里,只是该单元的名称。有时甚至会出现有效的错误消息被列出 2-4 次,直到“找到”循环引用问题。很明显,编译器在这里循环运行。由于该项目的规模,很难手动找到问题。因此,我制作了一个证明确实没有循环引用的工具(该工具创建了单元的有向依赖图并确定该图中的连贯性组件 - 除非我故意放一些中)。

这不仅会影响 F9 编译,还会影响大部分时间不起作用的代码完成/洞察力。有时当我第二次按 ctrl-space 时它会起作用...

有什么想法可以隔离甚至解决问题吗?请注意,将 40k LOC 单元拆分为较小的单元非常困难,因为它包含大约 15 个在接口部分相互依赖的大类(我知道这很糟糕,但无论如何应该可以工作)。

更新
我们一直在重构,但这是一个难以重构的单元,因为几乎一切都取决于一切。一直试图通过接口来解决它,但我们正在谈论一些具有 100 多个方法和属性的类。而且会慢一些。

升级到 D2009 可能是一个选择,但现在我们被 D2006 困住了(Unicode 的东西和价格标签是这里的两个障碍)。无论如何,问题是它是否会有所帮助,因为至少从 D6 开始就存在问题。

关于修剪使用条款,我们一直在使用 Icarus 进行此操作。但到目前为止,这并没有帮助。我们现在在界面部分减少了 90 个自定义单元。但是,对于真正的循环引用,问题可能出现在任何单元中。还尝试将所有单位添加到 dpr。

该项目与其他项目共享大量代码,并且有一些 IFDEF。但是,定义不是在项目选项中设置的,而是通过一个通用的包含文件设置的。因此所有模块都应该看到相同的定义。此外,在没有切换到另一个项目的情况下完全重建后不久,该问题再次出现。

【问题讨论】:

    标签: delphi


    【解决方案1】:

    我可能会因此而被否决。在 D2005 中,我有一个 10k loc 单元(数据模块)完全停止编译。不得不将一些数据集/代码分离到另一个数据模块。那个 10k 单位过去和现在都是一团糟。你真的应该考虑将一些代码重构到其他单元。自 D2005 以来,我的模块 / 分离变得更糟,但它仍然在 D2007 中编译。所以我的答案是 a) 重构 b) 升级到 D2009。

    【讨论】:

      【解决方案2】:

      很明显,这是由于后台编译器与真实编译器之间的细微差别所致。您可以查看 (QualityCentral) 关于该主题的已知信息。

      此外,由于您没有明确说明这一点,您应该删除不必要的单元,并尽可能将使用语句移至实现。也许你的工具可以帮助解决这个问题。

      为了确保您应该检查单位别名和路径设置。

      【讨论】:

        【解决方案3】:

        您写道,完整构建总是会成功,但在增量构建不久后会因此错误而失败。假设您在 IDE 中遇到过这种情况,您是否尝试过使用命令行编译器 dcc32 进行增量构建?

        如果您不向它提供“-Q”开关(可能大多数 Makefile 或命令行构建脚本都会这样做),它将输出大量信息,它会以什么顺序编译哪些文件。您可以在 IDE 中出现错误后尝试进行增量构建,或者您可以在 IDE 旁边打开一个命令行,然后按 Alt+Tab 进行编译,完全跳过 IDE 中的编译。

        我只是假设您有一种使用 dcc32 构建的方法,一种或另一种方式 - 以您的项目规模我无法想象。

        【讨论】:

        • 对,我们在所有项目(以及更多)的完整构建脚本中使用 dcc32。我并不是很期待用它来代替 IDE 编译;它对代码洞察力没有帮助,谁知道那时需要多长时间。但也许这是一种诊断问题的方法?理想情况下,dcc32 incremental 会遇到同样的问题,它的输出会引发一些想法......
        • 是的,这正是我试图建议的,但也许我没有成功说清楚:-( 抱歉。使用 dcc32 你应该看到哪些文件被编译了几次,之后文件一切都停止了。除非 IDE 编译器和 dcc32 真的那么不同,但我不会假设。
        【解决方案4】:

        我们经常遇到类似的问题,但我们从来没有设法(或打扰足够长的时间)找到确切的原因。 Delphi在按Ctrl-F9时选择编译单元的顺序似乎有问题,与单元的实际依赖顺序不兼容。

        • 您是否尝试在按 Ctrl-F9 之前删除“MyBigFatUnit.dcu”?
        • 您是否尝试过重新排序 dpr/dpk 文件中的单元声明,以便单元以正确的编译顺序显示? (即:如果单元 B 依赖于单元 A,则单元 A 应首先出现在 dpr/dpk 中)

        【讨论】:

          【解决方案5】:

          您还有其他项目使用相同代码库的一部分吗?如果您在不同的编译器设置或 IFDEF 下编译其中一个,它可能会更改某些 DCU 中的某些内容,从而导致循环依赖。完整构建会重建所有 DCU,然后问题就会消失。

          【讨论】:

            【解决方案6】:

            试试 Peganza 的 Icarus(免费)。如果这不能告诉您问题所在,请尝试他们的 Pascal Analyzer。

            【讨论】:

              【解决方案7】:

              我们也有这个问题,代码库也很大。

              我们目前使用的是 D2009,但在所有以前的 Delphi 版本中都遇到过这个问题。

              它最常发生在从源代码管理进行更新后立即发生,因此我怀疑 Delphi 构建过程中存在一些时间戳问题。

              在我们的例子中,如果 Ctrl-F9 失败并报告循环引用,第二个 Ctrl-F9 通常会起作用

              【讨论】:

                【解决方案8】:

                有人告诉我处理这个问题的方法是在项目中打开另一个任意文件,更改该文件,保存它,然后再次尝试运行增量编译。令人惊讶的是,这通常有效。

                我们有一个 4 MLOC 项目,它不时出现,这个“解决方案”对我有用。

                【讨论】:

                  【解决方案9】:

                  我以前也遇到过这种情况,根据我的经验,这个错误是准合法的。已经有一段时间了(错误与版本无关),但我对这种情况的记忆是它涉及一个循环,其中循环的一部分在实现中。

                  单元 A 在实现中使用 B。 B单元在接口中使用A。如果您首先编译 B 它会调用 A 但由于对 B 的调用在实现中它会成功。如果你先编译A,它会调用B,B转身在界面中调用A,boom。只有当两个交叉引用都在实现中时,这样的循环才是安全的。

                  解决方案是设计一些东西,以便界面中使用最少的东西,并确保这些单元中没有任何类似于循环的东西。只要您将类型定义与带有代码的单元分开,这很容易做到。

                  根据您所做的事情来来往往的错误是这个问题的一个标志,因为它归结为您如何进入循环。当您进行完整构建时,顺序是一致的,您可以得到 100% 或 0%,这不是随机的。

                  【讨论】:

                  • Loren,我明白你的意思 - 但你描述的是完全有效的代码,应该可以工作。它是这样记录的。大部分时间都可以工作的编译器仍然是一个损坏的编译器,对吧? FWIW,我曾经尝试将大部分“用途”从接口转移到实现。我不记得界面中有多少单位,但我记得它没有帮助。令人沮丧,为什么这个错误消息没有列出确切的循环引用?尤其是现在,当假定的圆圈是有效代码时,这将有助于大量了解必须更改的内容。
                  • @deepc:我同意它应该可以工作。好久没看到它了,我不记得措辞了,它不是给出了绊倒它的单位名称吗?我还发现命令行编译器对于弄清楚它很有用——将输出重定向到一个文件,这样你就可以实际看到它编译了哪些文件,而不仅仅是它现在正在处理什么。如果您将类型与代码分开,这几乎不是问题,除非您的单元布局是意大利面条。
                  猜你喜欢
                  • 1970-01-01
                  • 1970-01-01
                  • 1970-01-01
                  • 1970-01-01
                  • 1970-01-01
                  • 1970-01-01
                  • 1970-01-01
                  • 1970-01-01
                  • 2017-02-15
                  相关资源
                  最近更新 更多