vostro parametro S7
è dichiarato come parametro di out
, in modo che il compilatore impostare la variabile passata ad una stringa vuota quando viene chiamata la funzione. Stai passando la stessa variabile S
per tutti i parametri, incluso il parametro di output, quindi il valore di S
viene cancellato dalla memoria prima che i valori dei parametri vengano utilizzati all'interno della funzione.
Elaborare ulteriormente, la procedura utilizza la convenzione register
chiamata, dove S1
.. S3
vengono passati in registri della CPU (EAX, EDX, e ECX, rispettivamente) e S4
.. S6
vengono passati in pila invece. La grandezza di ingresso string
sta ottenendo spazzato chiaro dopo il suo valore attuale viene inserito nello stack per S4
e S5
(S3
e S6
sono solo rimandi alla variabile), e prima che il valore viene assegnato a S1
e S2
. Così, S1
e S2
finiscono nullo, S4
e S5
contengono puntatori ai dati originali 'S'
prima del wipe, e S3
e S6
sono rivolte l'una verso la variabile string
che è stato spazzato via.
Il debugger può mostrare tutto questo in azione. Se si mette un punto di interruzione alla linea dove MyProcedure()
si chiama, e quindi si apre la vista della CPU, potrete vedere le seguenti istruzioni di montaggio:
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
Per risolvere questo problema, è necessario utilizzare una variabile diversa per ricevere l'uscita :
procedure Work;
var
S, Res: String;
begin
S := 'S';
Proc(S, S, S, S, S, S, Res);
WriteLn(Res);
end;
alternativa, modificare la procedura in una funzione che restituisce un nuovo String
tramite il suo Result
invece di utilizzare un parametro out
:
function MyFunction(S1: String; const S2: String; var S3: String;
S4: String; const S5: String; var S6: String): String;
begin
Result := '1' + S1 + '2' + S2 + '3' + S3 + '4' + S4 + '5' + S5 + '6' + S6;
end;
procedure Work;
var
S: String;
begin
S := 'S';
WriteLn(MyFunction(S, S, S, S, S, S));
end;
Attenzione: quando dichiari un parametro con 'const', stai dicendo al compilatore che non dovrebbe aspettarsi che il parametro cambi per la durata di quella funzione. È tua responsabilità assicurarti di mantenere questa promessa; il compilatore non può controllarlo per te. In questo caso, stai modificando 'S' tramite' S7' mentre allo stesso tempo affermando che 'S2' e' S5' non cambieranno. –