Is Result variable defined from first line in a function?

后端 未结 3 1350
清歌不尽
清歌不尽 2021-01-12 01:34

I need a clarification of this case.

According my tests the Result variable is defined to: Boolean=False, Integer=0, String=\'\', Object=nil etc from the first line.

3条回答
  •  情歌与酒
    2021-01-12 01:54

    As stated by the official Delphi documentation, the result is either:

    • CPU register(s) (AL / AX / EAX / RAX / EAX:EDX) for ordinal values and elements contained in a register;
    • FPU register (st(0) / XMM1);
    • An additional variable passed as a latest parameter.

    The general rule is that no result value is defined by default. You'll have to set it. The compiler will warn you about any missing result set.

    For a string, dynamic array, method pointer, or variant result, the effects are the same as if the function result were declared as an additional var parameter following the declared parameters. In other words, the caller passes an additional 32-bit pointer that points to a variable in which to return the function result.

    To be accurate, the var parameter is not only for managed types, but only for record or object results, which are allocated on the stack before calling, so are subject to the same behavior.

    That is, for instance, if your result is a string, it will passed as an additional var parameter. So it will contain by default the value before the call. It will be '' at first, then if you call the function several times, it will contain the previous value.

    function GetString: string;
    // is compiled as procedure GetString(var result: string);
    begin
      if result='' then
        result := 'test' else
        writeln('result=',result);
    end;
    
    function GetRaise: string;
    // is compiled as procedure GetRaise(var result: string);
    begin
      result := 'toto';
      raise Exception.Create('Problem');
    end;
    
    var s: string;
    begin
      // here s=''
      s := GetString; // called as GetString(s);
      // here s='test'
      s := GetString; // called as GetString(s);
      // will write 'result=test' on the console
      try
        s := GetRaise; // called as GetRaise(s);
      finally
        // here s='toto'
      end;
    end;
    

    So my advices are:

    • Fix all compiler warning about unset result;
    • Do not assume that a result string is initialized to '' (it may be at first, but not at 2nd call) - this is passed as a var parameter, not as a out parameter;
    • Any exception will be processed as usual, that is, the running flow will jump to the next finally or except block - but if you have a result transmitted as a var parameter, and something has been already assigned to result, the value will be set;
    • It is not because in most cases, an unset result ordinal value (e.g. a boolean) is 0 (because EAX=0 in asm code just before the return), that it will be next time (I've seen random issues on customer side because of such unset result variables: it works most time, then sometimes code fails...);
    • You can use the exit() syntax to return a value, on newer versions of Delphi.

提交回复
热议问题