PFeng
PFeng

Reputation: 101

out parameter and "ShowMessage" function

I have a function declare like this :

function execProc(ProcName,InValues:PChar;out OutValues:PChar):integer; //The "OutValues" is a out parameter.

And I call this function like this:

procedure TForm1.Button6Click(Sender: TObject);
var
 v:integer;
 s:pchar;
begin
 Memo1.Clear;
 v := execProc(pchar('PROC_TEST'),pchar('aaa'),s);
 showmessage(inttostr(v)); //mark line
 Memo1.Lines.Add(strpas(s));
end;

when i delete the mark line(showmessage(inttostr(v))),i will have a correct result display in the Memo1,but if i keep use the showmessage(), the memo1 will dispaly an error string : "Messag" ,Why? Thanks for any help!

function execProc(ProcName,InValues:PChar;out OutValues:PChar):integer;
var
  str: TStrings;
  InValue,OutValue: string;
  i,j,scount: integer;
begin
Result := -100;
i := 0;
j := 0;
str := TStringList.Create;
try
  sCount := ExtractStrings(['|'], [], InValues, str);
  with kbmMWClientStoredProc1 do
  begin
    Close;
    Params.Clear;
    StoredProcName := StrPas(ProcName);
    FieldDefs.Updated := False;
    FieldDefs.Update;
    for i := 0 to Params.Count - 1 do
    begin
      if (Params[i].ParamType = ptUnknown) or
       (Params[i].ParamType = ptInput) or
       (Params[i].ParamType = ptInputOutput) then
      begin
        inc(j);
        InValue := str[j-1];
        Params[i].Value := InValue;
      end;
    end;
    try
      ExecProc;
      for i := 0 to Params.Count - 1 do
      begin
        if  (Params[i].ParamType = ptOutput) or
       (Params[i].ParamType = ptInputOutput) then
         OutValue := OutValue + '|' + Params[i].AsString;
      end;
      OutValues := PChar(Copy(OutValue,2,Length(OutValue)-1));
      Result := 0;
    except
      on E:Exception do
      begin
        if E.Message = 'Connection lost.' then Result := -101;//服务器连接失败
        if E.Message = 'Authorization failed.' then Result := -102;//身份验证失败
        Writelog(E.Message);
      end;
    end;
  end;
finally
  str.Free;
end;
end;

Upvotes: 1

Views: 1462

Answers (1)

David Heffernan
David Heffernan

Reputation: 613412

The problem is in the design of your interface and the use of PChar.

OutValues := PChar(Copy(OutValue,2,Length(OutValue)-1));

This is implemented by making an implicit, hidden, local string variable which holds the value

Copy(OutValue,2,Length(OutValue)-1)

When the function returns, that string variable is destroyed and so OutValues points at deallocated memory. Sometimes your program appears to work but that's really just down to chance. Any small change can disturb that, as you have observed.

The problem is easy enough to fix. Simply use string parameters rather than PChar. This will make the code easier to read as well as making it work correctly.

function execProc(ProcName, InValues: string; out OutValues: string): integer;

Upvotes: 2

Related Questions