Delphi: non-deterministic access violation using RTTI to set object properties from TMemo.Text
我正在构建一个非常粗糙的 GUI 来建模映射器,它基本上遍历表单上的所有 TEdit 和 TMemo 字段,提取文本并将该文本设置在数据模型对象中。 (解决方案取决于我承认的脆弱的”约定优于配置”方法,仅匹配数据模型中与表单中的字段具有相同名称的属性。)
免责声明:对于臃肿的代码示例感到抱歉。这里是:
表格。
1
2 3 4 5 6 7 8 9 |
{ Standard interface section above this line }
type TfrmMain = class(TForm) StringField1: TEdit; StringField2: TMemo; { Other fields and procedures dropped for brevity } private procedure FillGUIFields(); end; |
数据模型。
1
2 3 4 5 6 7 8 9 |
TDataModel = class(TObject)
private FStringField1: string; FStringField2: string; { Getters and setters dropped for brevity } public property StringField1: string read GetFStringField1 write SetFStringField1; property StringField2: string read GetFStringField2 write SetFStringField2; end; |
实现。
1
2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 |
const
MAX_RUNS = 100; procedure GUIToData(var AObject: TObject; const Form: TForm); procedure TfrmMain.btnFetchToModelClick(Sender: TObject); function TDataModel.GetFStringField1: string; procedure TDataModel.SetFStringField1(Value: string); { Identical getter/setter for StringField2 } procedure TfrmMain.FillGUIFields; end. |
当我运行它时,在大约 27% 的情况下我会遇到访问冲突异常。如果我只设置与 TEdit 字段名称匹配的属性(即 StringField1),则不会发生异常。如果我直接访问字段(让 getter/setter 直接指向字段或在 GUIToData 过程中使用 t.GetFields),则不会引发访问冲突。
人们能够复制这个吗?有谁知道是什么导致了这种奇怪的行为?谢谢!
- 您使用的是哪个版本的 Delphi?
- 既然您说它在删除 setter 方法时有效,请尝试将”const”添加到 setter 中,如下所示:”SetFStringField1(const Value: string);”
- @Ville:我正在运行 D2010。 const 建议真的很有趣,但是我无法验证它,因为我现在无法重现 AV。不过,明天我会再试一次。
- 我在 Delphi XE 上运行它,每次都运行良好。显然,您的示例代码中缺少某些内容。 (或者您正在使用 D2010 及其在 XE 中修复的错误。)
- 我刚刚在 D2010 中尝试过,每次都运行良好。
- 使用调试器时会发生什么?什么被非法访问,如何访问?尝试使其具有确定性;当您发现代码崩溃的情况时,请消除随机性并每次都重现该确切情况。
- @Mason/@Rob:上面的代码实际上是一个更大框架的淡化版本,这个问题第一次出现的地方。我试图拿出似乎是必需品的东西。我必须再次检查该过程,因为当我重新启动 RAD Studio 时,问题从淡化版本中消失了。我家里没有原始问题源,所以我得等到明天才能完全复制它。
好的。所以这就是发生的事情。
重新启动 RAD Studio 并没有解决问题 – 即我仍然能够重现。然后我让一个同事在他的电脑上编译项目,没有出现异常。相同的代码和相同的 RAD Studio 版本(显然 – 我们都运行 D2010 版本 14.0.3513.24210)。然后我让我的同事在他的机器上运行我失败的可执行文件,它的行为与我的计算机上的完全一样。 (我们在十六进制编辑器中比较了他和我电脑中的 exe,结果发现非常明显的差异。)
然后,我们比较了与 D2010 捆绑的 Win32 源。那里也有很多差异,特别是在 Classes.pas 和 RTTI.pas.
我的 D2010 设置一定有问题。解决方案?运行 RAD Studio 2010 Update 4 解决了我的问题(现在运行 D2010 版本 14.0.3593.25826)。原因?我想我永远不会知道。
来源:https://www.codenong.com/7674038/