10

我在我的项目中使用此代码:

var
  P: TPoint;

MyControl.Perform(WM_LBUTTONDOWN, 0, Longint(PointToSmallPoint(P)));

编译器给了我一个警告:

[Warning]: Unsafe typecast of 'TSmallPoint' to 'Integer'

但是,在Controls.pas 没有任何警告的情况下使用相同的代码- 例如在TControl.BeginDrag方法中:

....
Perform(WM_LBUTTONUP, 0, Longint(PointToSmallPoint(P)));

我没有看到任何{$warnings off}单位Controls.pas

为什么编译器警告我,但跳过警告Controls.pas
这段代码不安全吗?


编辑:在我的项目选项 -> 编译器消息 -> 不安全类型转换中选中(默认情况下未选中)。
也许这就是@David 和@Ken 无法重现警告的原因。

4

2 回答 2

11

这是因为您unsafe typecast在 Project->Options->Compiler Messages 中检查了警告。取消选中是安全的(与它一样unsafe typeunsafe code以上。(见下文。)

我无法重现警告,因为我未检查不安全的类型转换。它不再适用。(当他们为 .NET 开发 Delphi 时,为了与 .net 兼容而在 Delphi 6 或 7 中添加了它,以便更轻松地编写适用于 .NET 和 Win32 的代码;由于 .NET 产品的 Delphi 已停产,因此该警告(以及上面的两个)不再适用)。这三个警告中的“不安全”使用 .NET 的“不安全”含义,意思是“非托管”。

从 Delphi 7 帮助文件(搜索“编译器更改”)(强调我的):

Delphi dcc32 编译器现在支持三个额外的编译器警告:Unsafe_Type、Unsafe_Code 和 Unsafe_Cast。 默认情况下禁用这些警告,但可以使用编译器指令 {$WARN UNSAFE_CODE ON}、编译器命令行开关 (dcc32 -W+UNSAFE_CODE) 以及在 IDE 中的项目|选项|编译器消息页面上启用。

此功能旨在帮助您将代码移植到 Microsoft .NET 平台的托管执行环境。在托管执行环境中,“不安全”是指在即时 (JIT) 编译器执行的静态分析期间无法验证操作。此类代码可能会带来安全风险,因为 JIT 编译器没有足够的信息来验证其运行时行为。不安全代码的示例包括指针操作和内存覆盖。

于 2012-12-28T23:28:23.513 回答
5

如果您自己编译 Controls 单元并启用不安全类型转换警告,那么您将看到警告。但是,如果您链​​接预构建的 .dcu 文件,则不会看到任何警告。编译器只对它编译的单元发出警告。

作为一般规则,RTL 和 VCL 单元会生成大量提示和警告。如果我必须重新编译它们,我总是必须关闭这些单元上的提示和警告。


警告的现代文档说:

您使用了静态代码分析无法证明它不会覆盖内存的数据类型或操作。例如,您可能已经将一个记录(原文如此)到另一个或一个实例到另一个。

该警告确实适用于您的代码。您的代码不安全。编译器无法验证将两个 16 位整数叠加到一个 32 位整数上是否正确。所以编译器会警告你。代码是否正确由您决定。

现在,该警告似乎主要针对 .net 编译器。尽管如此,它仍然对 Win32 编译器有意义。将一个记录叠加在另一个记录上是可疑的行为。

于 2012-12-28T23:21:47.450 回答