[fpc-devel] Re: "dynamic array of char" vs. "out array of char"

Seth Grover sethdgrover at gmail.com
Wed Apr 28 02:35:02 CEST 2010

Graeme wrote:
> Changing those two procedures to the following code shown below works fine.
> ...
> Also, your initial code for the second array should actually be inside the
> DoItOut() procedure

Yes, I know it works if you change the "array of char" parameters to
simply reflect the dynamic array type. I was doing it that way to
illustrate the crash. Also, I know the "fillchar" on the second
example is ineffectual, however, it's how you get it to crash. If you
don't have something in the array before the second call, it doesn't
crash. This is because in the call to fpc_dynarray_decr_ref it appears
to be dereferencing a pointer that's already dereferenced, but if the
array is empty to begin with it just so happens that the data there is
full of #0 characters so it doesn't make it past the "nil" check.

Jonas, thank you for the explanation about "out" vs. "var" when it
comes to reference counted data. I'd not stopped to think about it,
but that makes perfect sense. And, looking at the assembly code, you
are correct, it is the attempt to get the reference count that causes
it to crash.

> The compiler should simply refuse to compile your program.

As for that, I understand what you're saying, but I'm not sure I feel
the same way. Or, better said, I am glad that it *does* work (as long
as I use "var" instead of "out.") The reason being is I have quite an
extensive unit which does manipulations on arrays of characters:
however, I have some variables in records which are declared as
static, fixed arrays and others declared like "type myType = array of
char." As it currently works, I am able to pass both kinds as open
array of char arguments and it all just works (well, now that I've
gone through and replaced the "out" with "var" :)). When I say it just
works, I mean the the correct pointer and high bound is passed in both
cases. If the compiler were to forbid me to do that I'd be unable to
use a single set of these routines for both cases.

>From what I could see in the assembler code, when the parameter was
declared as "out whatever : array of char" and I passed in a typed
dynamic array variable, in the call to fpc_dynarray_decr_ref called
before my procedure was called it appears it was trying to dereference
the memory where the array data was stored, but that register already
contains the pointer to the data, so there's no need to dereference
it. However, once I realized that I really wanted "var" rather than
"out", the call to fpc_dynarray_decr_ref is, of course, no longer
being made, and it just works.

Thanks again for the input.

And, as a side note, as I tell all my developer friends, the FPC
community of developers and users is just top-notch. Thanks so much
for the effort and high quality that is the Free Pascal compiler, and
for always being so informative, helpful, and accessible when it comes
to the mailing list discussions. You guys really are a class act. At
my company we're just finishing converting a couple of million lines
of code from Modula-2 to Object Pascal using the Free Pascal compiler
and it's incredible how smooth the transition has been. And when I
have run into roadblocks or questions, the mailing lists have been so
helpful. Anyway, I just wanted to say "thanks."


This email is fiction. Any resemblance to actual events
or persons living or dead is purely coincidental.

Seth Grover

On Tue, Apr 27, 2010 at 3:21 PM, Seth Grover <sethdgrover at gmail.com> wrote:
> Observe the following test program (http://pastebin.org/186091 for
> those who prefer):
> ============================================================
> program dynarrayout;
> {$mode objfpc}{$H+}
> uses
>  SysUtils;
>  procedure DoItVar(var yourArray : array of char);
>  begin
>  end;
>  procedure DoItOut(out yourArray : array of char);
>  begin
>  end;
> type
>  DynCharArray = array of char;
> var
>  myArray : DynCharArray;
>  myArray2 : DynCharArray;
> begin
>  SetLength(myArray, 64);
>  try
>    FillChar(myArray[0], Length(myArray), '!');
>    DoItVar(myArray);
>    writeln('DoItVar is ok');
>  except
>    on E : Exception do begin
>      writeln('Exception calling DoItVar: ', E.Message);
>    end;
>  end;
>  SetLength(myArray, 0);
>  SetLength(myArray2, 64);
>  try
>    FillChar(myArray2[0], Length(myArray2), '~');
>    DoItOut(myArray2);
>    writeln('DoItOut is ok');
>  except
>    on E : Exception do begin
>      writeln('Exception calling DoItOut: ', E.Message);
>    end;
>  end;
>  SetLength(myArray2, 64);
> end.
> ============================================================
> So basically I have a type defined as a dynamic array of characters,
> which I fill with some data. If I have a function which takes a
> parameter which is a "var array of char" into which I pass a variable
> of my dynamic array type it works fine. However, if I have a function
> where the parameter is an "out array of char", I get a crash when I
> try to pass in my variable.
> Is this behavior correct? Can someone explain this to me? I thought
> that the only difference between "var" and "out" was whether or not
> the compiler warned you about uninitialized data.
> Thanks,
> -SG
> --
> This email is fiction. Any resemblance to actual events
> or persons living or dead is purely coincidental.
> Seth Grover
> sethdgrover[at]gmail[dot]com

More information about the fpc-devel mailing list