代码之家  ›  专栏  ›  技术社区  ›  JosephStyons

我可以重新编译DelphiIDE使用的.pas文件吗?

  •  4
  • JosephStyons  · 技术社区  · 15 年前

    我熟悉 Jeff Atwood's article about how errors are always the programmer's fault 但我相信我确实在delphi.pas文件中发现了一个bug。

    具体来说,我使用的是Delphi2007,错误出现在dbcommon.pas文件的第955行,该文件位于我的计算机上:

    C:\程序文件\codegear\rad studio\5.0\source\win32\db\dbcommon.pas

    代码是这样的:

    ...
      FieldIndex := StrToInt(Token);
      if DataSet.FieldCount >= FieldIndex then
        LastField := DataSet.Fields[FieldIndex-1].FieldName else
    ...
    

    如果“token”的值为零,那么我们尝试访问dataset.fields的index-1,从而导致列表索引越界错误。

    这个错误不会对用户产生,因为它是在它变得如此高之前处理的,但是每次发生这种情况时都让调试程序中断是非常令人恼火的。

    我可以“忽略这个异常类型”,但是索引越界错误非常常见,我不想完全忽略它们。

    导致fieldindex为零的情况是,当您有一个select语句,其order by包含一个函数时,如:

    ORDER BY
      CASE WHEN FIELD1 = FIELD3 THEN 1 ELSE 2 END
     ,CASE WHEN FIELD2 = FIELD4 THEN 1 ELSE 2 END
    

    我可以在dbcommon.pas中修复这个bug,但是delphi不会重新编译自己,我的更改也不会生效。如果我重命名.dcu文件,它只会抱怨找不到“dbcommon.dcu”。

    所以(最后)我的问题是:我可以用我的修复程序重新编译dbcommon.pas吗?如果可以,如何重新编译?

    7 回复  |  直到 11 年前
        1
  •  12
  •   Tom    15 年前

    您可能可以将dbcommon.pas放在项目目录中。然后,它将与项目的其余部分一起编译。

        2
  •  4
  •   Deltics    15 年前

    有关如何创建可以重新编译已修改VCL源的情况,请参阅前面的答案。不过,我想补充一点,您应该认真考虑使用“供应商分支”的SCM模式来管理变更控制系统中的变更。

    简单来说(使用SVN作为参考):

    • 创建原始供应商提供文件的“供应商源”副本。这是你的“原始”参考副本。

    • 创建一个代表原始副本的分支(例如,对于Delphi2009版本的VCL,“2009”)。

    • 将另一个分支创建到单独的“供应商库”文件夹中。这是应该在项目中引用的库的副本

    • 对供应商源代码的任何修改都在“供应商库”分支中进行。

    • 当供应商提供库的新版本时,您将新版本签入“供应商源”项目,并为新版本创建新分支。

    然后您可以轻松地区分供应商的修订。但更重要的是(使用Subversion,可能还有其他的SCM系统),您还应该能够简单地将新的供应商源代码与“供应商库”分支合并(即自动合并),以便将供应商更改与您自己的修改结合起来。

    这一切都比我刚才在一本优秀的O'Reilly书《颠覆版本控制》中描述的好得多。

    但是请注意,由于版权问题,该书中提到的“loaddirs”实用程序不再受支持,因此更新“vendor drops”目前是一种手动操作,但这种情况很少发生,也不是主要的负担。

    我们自己也在使用这种模式,尽管在VCL的情况下,我们没有在“供应商源”或“供应商库”中维护整个VCL源树的完整副本,而是只跟踪更改的和依赖的单元。对于由供应商分支机构管理的其他库,我们通常维护完整的副本,但认为这对于VCL来说不是必需的。

    不过,我们只是实现了这个模式,所以我们可能还需要对VCL采取更全面的方法。

    牛传染性胃肠炎病毒

        3
  •  4
  •   Rob Kennedy    15 年前

    你可以,但通常你不需要。有时,重新编译VCL单元意味着重新编译所有剩余的VCL单元,要么是因为您更改了单元的接口,要么是因为编译器混淆了 认为 您已更改接口。重新编译VCL单元也排除了使用大多数运行时包的可能性,因为您不能重新编译Delphi的运行时包。

    您可以使用运行时修补来代替重新编译。我用了这个方法 TNT Unicode controls 但是 Madshi 还提供了用自己的实现替换函数的方法。如果将dbcommon.getindexfororderby的实现复制到自己的单元中并进行修复,则可以使用此命令使用自己的单元修补VCL版本:

    var
      Old_GetIndexForOrderBy: Pointer;
    
    HookCode(@DBCommon.GetIndexForOrderBy,
             @Fixed_GetIndexForOrderBy,
             Old_GetIndexForOrderBy,
             0);
    

    使用TNT Unicode库,查找 OverwriteProcedure TNT系统单元中的例行程序。它不是公共的,所以您需要在单元接口中声明它或者将它复制到您自己的单元中。然后,您可以像上面的Madshi代码一样调用它:

    var
      Old_GetIndexForOrderBy_Data: TOverwrittenData;
    
    OverwriteProcedure(@DBCommon.GetIndexForOrderBy,
                       @Fixed_GetIndexForOrderBy,
                       @Old_GetIndexForOrderBy_Data);
    
        4
  •  2
  •   Conor Boyd    15 年前

    我们在项目源树下有一个名为VCL的文件夹,我们将希望稍微修改的VCL源的副本放入其中。 你的例子很适合做同样的事情。 您需要修改项目的搜索路径,以便“您的”VCL文件夹在您的路径上比Delphi安装下的“源”文件夹更早。 您还可能发现,如果您复制一个VCL源单元并对其进行修改,则还必须将其他VCL源单元复制到“your”文件夹中,该文件夹可能是依赖项。

    我们这样做的原因是我们希望构建没有编译器提示和警告。VCL源的某些部分没有提示/警告。

        5
  •  2
  •   IceCold    14 年前

    “我很熟悉Jeff Atwood的文章,关于错误总是程序员的错误,但我相信我确实在delphi.pas文件中发现了一个错误。”

    你在开玩笑吗?有了德尔菲,你总是先怪博兰:) 有点奇怪,去谷歌看看它是不是一个德尔福错误。只有当你找不到任何类似的报告,你的网站和检查你的代码一行一行。

    重新安装Delphi之后,我必须在6(6)个位置修补原始的pas文件。在一个新的Delphi安装中出现了大量的bug,并且很容易被复制。德尔菲(我们都喜欢的那个)充满了虫子。围绕这一点有一个完整的历史。 有那么多人在释放外部补丁(例如 http://andy.jgknet.de/blog/?page_id=288 )博兰/监狱/戈格尔/埃巴卡德罗一直忽视他们。真奇怪,他们在发行版中加入了Fastmm。

    不管怎样,我已经重新编译了这些PAS文件,现在我用修补后的文件替换了原来的DCU。

        6
  •  1
  •   Despatcher    15 年前

    很简单-是的。使用上述答案之一[由汤姆或康纳]。将dbcommon.pas复制到项目文件夹,而不是编辑原始文件。这会使其他项目和编译不受影响,因为它不会在路径上。

        7
  •  1
  •   Franck Dernoncourt    11 年前

    您可以设置: DataSetProvider.Option.poRetainServerOrder = True