Delphi程序带字符串参数

时间:2016-03-10 20:30:24

标签: delphi delphi-7

我在使用Delphi中的过程和字符串时遇到了问题。事实是,我希望看到输出字符串" 1S2S3S4S5S6S"但实际输出是" 1234S5S6"。在调试过程中,它表示没有初始化S1,S2,S3和S6字符串变量(S1,S2,S3,S6是'''''''' S' )。有人可以向我解释一下吗?这是代码:

program StringTest;

{$APPTYPE CONSOLE}

procedure MyProcedure(S1: String; const S2: String; var S3: String;
                      S4: String; const S5: String; var S6: String;
                      out S7: String);
begin
  S7 := '1' + S1 + '2' + S2 + '3' + S3 + '4' + S4 + '5' + S5 + '6' + S6;
end;

procedure Work;
var
  S: String;
begin
  S := 'S';
  MyProcedure(S, S, S, S, S, S, S);
  writeln(S);
end;

begin
  Work;
  readln;
end.

1 个答案:

答案 0 :(得分:17)

您的S7参数被声明为out参数,因此编译器会在调用函数时将传递的变量设置为空字符串。您正在为所有参数传递相同的S变量,包括输出参数,因此在函数内部使用参数值之前,S的值将从内存中擦除。

进一步详细说明,该过程使用register调用约定,其中S1 .. S3在CPU寄存器(分别为EAX,EDX和ECX)中传递,{ {1}} .. S4代替传递给堆栈。输入S6变量在其当前值被推送到stringS4的堆栈后被清除,S5S3只是指向变量),并在将值分配给S6S1之前。因此,S2S1结束为零,S2S4包含指向擦除之前原始S5数据的指针,'S'S3指向已擦除的S6变量。

调试器可以向您展示所有这些。如果在调用string的行放置断点,然后打开CPU视图,您将看到以下汇编指令:

MyProcedure()

要解决此问题,您需要使用其他变量来接收输出:

StringTest.dpr.17: MyProcedure(S, S, S, S, S, S, S);
00405A6C 8B45FC           mov eax,[ebp-$04]  // [ebp-$04] is the current value of S
00405A6F 50               push eax           // <-- assign S4
00405A70 8B45FC           mov eax,[ebp-$04]
00405A73 50               push eax           // <-- assign S5
00405A74 8D45FC           lea eax,[ebp-$04]
00405A77 50               push eax           // <-- assign S6
00405A78 8D45FC           lea eax,[ebp-$04]
00405A7B E8B0EDFFFF       call @UStrClr      // <-- 'out' wipes out S!
00405A80 50               push eax           // <-- assign S7
00405A81 8D4DFC           lea ecx,[ebp-$04]  // <-- assign S3
00405A84 8B55FC           mov edx,[ebp-$04]  // <-- assign S2
00405A87 8B45FC           mov eax,[ebp-$04]  // <-- assign S1
00405A8A E8B9FEFFFF       call MyProcedure

或者,将过程更改为通过其procedure Work; var S, Res: String; begin S := 'S'; Proc(S, S, S, S, S, S, Res); WriteLn(Res); end; 而不是使用String参数返回新Result的函数:

out