我在我的项目中使用此代码:
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
的警告?
这段代码不安全吗?
编辑:在我的项目选项中 - >编译器消息 - >检查不安全的Typecast (默认情况下未选中) 也许这就是@David和@Ken无法重现警告的原因。
答案 0 :(得分:11)
这是因为您在Project->选项 - >编译器消息中检查了unsafe typecast
警告。取消选中是安全的(如unsafe type
和unsafe code
一样。(见下文。)
我无法重现警告,因为我已取消选中不安全的类型转换。它已不再适用。 (当他们开发Delphi for .NET时,它在Delphi 6或7中添加了.net兼容性,以便更容易编写适用于.NET和Win32的代码;因为Delphi for .NET产品已停止使用,该警告(以及它上面的两个)不再适用)。这三个警告中的“不安全”使用“不安全”的.NET含义,意思是“不受管理”。
从Delphi 7帮助文件(搜索“编译器更改”)(强调我的):
Delphi dcc32编译器现在支持三个额外的编译器警告:Unsafe_Type,Unsafe_Code和Unsafe_Cast。 默认情况下禁用这些警告,但可以使用编译器指令{$ WARN UNSAFE_CODE ON},编译器命令行开关(dcc32 -W + UNSAFE_CODE)以及IDE中的项目启用|选项|编译器消息页面。
此功能旨在帮助您将代码移植到Microsoft .NET平台的托管执行环境中。在托管执行环境中,“不安全”意味着在Just In Time(JIT)编译器执行静态分析期间无法验证操作。此类代码可能会带来安全风险,因为没有足够的信息用于JIT编译器验证其运行时行为。不安全代码的示例包括指针操作和内存覆盖。
答案 1 :(得分:5)
如果您自己编译控制单元,并启用了不安全的类型转换警告,那么您将看到警告。但是如果你链接预先构建的.dcu文件,那么你看不到任何警告。编译器仅对其编译的单元发出警告。
作为一般规则,RTL和VCL单元会生成大量提示和警告。如果我不得不重新编译它们,我总是要在这些单元上关闭提示和警告。
警告的现代documentation说:
您使用的数据类型或操作静态代码分析无法证明它不会覆盖内存。例如,您可能已将(原文如此)一条记录装入另一条记录或将一个实例装入另一条记录。
该警告确实适用于您的代码。您的代码不安全。编译器无法验证将两个16位整数叠加到32位整数上是否正确。所以编译器警告你。由您决定代码是否正确。
现在,警告似乎主要用于.net编译器。尽管如此,它仍然对Win32编译器有意义。将一条记录叠加在另一条记录上是可疑行为。