当我在Delphi 10.2.3 Pro中编写一个函数,该函数具有记录作为返回值,而只是将其保留为空时,我不会收到W1035“ W1035函数'%s'的返回值可能未定义”的警告。为什么我没有收到警告?
谢谢!
答案 0 :(得分:1)
不幸的是,对于非托管记录,警告也被取消。我猜想原因是编译器很难跟踪所有字段的变化。另外,如果您修改记录的一个字段,是否将整个记录视为已定义?
这是要测试的代码:
{$O-}
type
TRecordType = record
a, b: Word;
end;
function Test: TRecordType;
begin
end;
procedure TForm1.FormCreate(Sender: TObject);
var
v: TRecordType;
begin
v := Test;
ShowMessage(Format('%d, %d', [v.a, v.b]));
end;
它确实为我提供了随机数(如果重复运行,则不会更改,因为堆栈几乎相同)。
用于调用的汇编代码:
0046CCA9 E8CAFFFFFF call Test
0046CCAE 8945F8 mov [ebp-$08],eax
Test
的汇编代码:
0046CC78 55 push ebp
0046CC79 8BEC mov ebp,esp
0046CC7B 51 push ecx
0046CC7C 8B45FC mov eax,[ebp-$04] ; eax is the result, not initiated
0046CC7F 59 pop ecx
0046CC80 5D pop ebp
0046CC81 C3 ret
当记录的大小不是1、2、4时,结果将通过引用作为隐藏参数传递。例如,如果a
和b
为integer
,则用于调用的汇编代码将变为
0046CCAA 8D45F4 lea eax,[ebp-$0c] ; address of V, V is not initiated
0046CCAD E8C6FFFFFF call Test
Test
的汇编代码:
0046CC78 55 push ebp
0046CC79 8BEC mov ebp,esp
0046CC7B 51 push ecx
0046CC7C 8945FC mov [ebp-$04],eax
0046CC7F 59 pop ecx
0046CC80 5D pop ebp
0046CC81 C3 ret
因此,在两种情况下,结果都是不确定的,没有警告。
答案 1 :(得分:0)
从我的角度来看,这显然是编译器警告生成器中的错误。
对于记录,编译器必须比对整数或实数之类的简单类型进行更多检查。例如,您在这里期望什么:
function Test: TRecordType;
begin
result.a := 1;
end;
因为记录的一部分(对于b而言)是未定义的,所以编译器在此处也应提及W1035。另一方面,对于具有不同案例的记录,您会有什么期望?
TRecordType = record
ID: string;
case boolean of
true:
(a: integer);
false:
(b: string);
end;
正如您在此处看到的,无法确定记录是否已完全初始化。至少如我们在TRecordType是类的情况下所见,如果未分配记录的静态字段,则至少Delphi编译器可以发出警告。
我建议在Embarcadero质量报告端输入此错误 https://quality.embarcadero.com 并在堆栈溢出时对此线程进行引用。