这个问题与我之前的问题有关:
access violation at address in module ntdll.dll - RtlEnterCriticalSection with TCanvas.Lock
显然,Delphi的代码中存在一个错误(请参阅QC 64898: Access violation in FreeDeviceContexts)。这个错误一直持续到D2010,AFAIK。
到目前为止,建议的解决方法运行良好。现在我陷入两难境地。
我不喜欢在我的项目中使用db.query("SET CHARACTER SET utf8;")
的私人副本 - 我不确定它是否安全。 Controls.pas
单位是一个非常低级别的单位,考虑到我的巨大应用程序工作正常,除了提到的问题,我真的觉得这是一个激烈的举动。我还不确定是否/如何重建依赖项目中Controls
单元的所有组件/单元。
是否可以修补使用内部Controls
和私人成员的TControlCanvas.CreateHandle()
?
注意:我将仅使用此项目的补丁(Delphi 5)。我不介意对补偿进行硬编码。 AFAIK,修补privates总是使用基于编译器版本的硬编码偏移。我可能能够自己处理私有(没有类帮助程序),但我不知道如何处理CanvasList
和CanvasList
,它们在实现部分中声明FreeDeviceContext()
单位。
答案 0 :(得分:2)
正如评论中所讨论的那样, 可以访问类的private
和protected
成员,即使在没有“类助手”的旧版Delphi中也是如此。< / p>
但是,本案中的问题围绕特定方法实现的细节,而不仅仅是能够访问或修改私有成员变量。此外,实现了在所涉及的单元中使用实现变量的特定方法。特别是您注意到的CanvasList
变量。
即使有了类助手的好处,也没有简单的方法可以访问该实现变量。
您当前的解决方案是最简单,最安全的方法:使用整个单元的副本,并将修改应用于解决问题所需的特定方法。
请放心,这不是一种罕见的做法。 :)
这种方法的唯一问题是确保在新的开发环境或升级到新版本的IDE时,依赖于该单元的“私有化”副本这一事实。
对于新的开发环境,仔细的项目配置应该处理事情(当然,您修改的Controls.pas
单元是版本控制项目的一部分。)
在升级到较新的Delphi版本的情况下,您只需记住在每个新版本中重新访问修改后的Controls
单元,更新项目中的私有副本并重新应用您所做的修改适当。在大多数情况下,如果不是所有情况,这应该是直截了当的。
正如我上面所说,没有简单方式来访问该单元中使用的实现变量(如果你想以某种方式设法在运行时“修补”代码,那将是必要的,而不是而不是在编译时用修改后的副本替换它。)
但这意味着有一种非**的简单方法。还有。
与应用程序中的任何数据一样,该变量位于进程中的某个内存地址。它只是编译器范围规则阻止您直接在源代码中解决它。没有什么可以阻止你弄清楚如何在运行时找到该位置并通过指针寻址该内存位置,就像你可以访问的任何其他“原始”内存地址一样。
我没有一个如何做到的工作演示,并强烈建议尝试实施这样的解决方案是浪费时间和精力,因为存在更简单的解决方案(复制和修改单元)。 / p>
除了其他任何内容之外,根据确定所涉及的内存位置的方法的可靠性,直接访问该内存位置可能不仅容易受到编译器版本之间的差异的影响,甚至可能容易受到编译器设置引起的更改的影响。
就最终结果而言,它并不比复制单位好,但肯定要难得多,也不那么可靠。