I believe it is a compiler error and will raise a QA ticket

Thanks for your  help


D


On 26/08/11 08:17, Peter Ingham wrote:
> Try filling LogData with binary zeros after the Getmem&  before the assign.
>
> FillChar (LogData^, sizeof(TLogData), 0);
>
> I believe the uninitialized memory is messing up the compiler magic
> associated with the dynamic array.
>
>
> Any reason the local Tlogdata record is referenced via a pointer?
>
> I suspect the following will also work:
> procedure TUserClass.Log(const LogType: TLogType; const Args: array of
> const );
>    var
>       LogData: TLogData;
>     begin
>       LogData.LogType := LogType;
>       LogData.LogArgs := CreateConstArray(Args);
>       //  ... do some other stuff with the LogData item finally calling
>     end;
>
> Cheers
>
> On 26/08/2011 1:49 a.m., David Moorhouse wrote:
>> Hi Peter
>>
>> Been there done that :)
>>
>> The function call is fine.  It is the assignment that causes the AV -
>> because the "bucket" is too small.
>> Assigning it with 16 bytes fixes the problem, regardless of how many
>> items the array holds.
>>
>> I smell compiler magic in the background.
>>
>> Cheers
>
>> D
>>
>> On 25/08/11 17:29, Peter Ingham wrote:
>>> Another attempt to reply...
>>>
>>> First thing to do is determine if the crash occurs in the procedure call,
>>> on the subsequent assign, or in between.
>>>
>>> Give this a try:
>>>    procedure TUserClass.Log(const LogType: TLogType; const Args: array of
>>>    const );
>>>    var
>>>      LogData: PLogData;
>>>     TempArgs : TConstArray;
>>>    begin
>>>        // size of record TLogData does not work
>>>        GetMem(LogData, sizeof(TLogData));
>>>        LogData.LogType := LogType;
>>>    // blows up on one of these lines
>>>        TempArgs  := CreateConstArray(Args);
>>>        LogData.LogArgs := TempArgs;
>>>    //  ... do some other stuff with the LogData item finally calling
>>> FreeMem
>>>    end;
>>>
>>>
>>> Regarding the size of a dynamic array,  like a string variable,  the
>>> variable (LogArgs in this case) is the size of a pointer (i.e. 4 bytes
>>> for Win32).  If the pointer is non-zero, it points to a structure which
>>> includes the adjacent array elements preceded by a length.
>>>
>>> One thing to watch out for is that Getmem does not clear the allocated
>>> memory, so LogData after the Getmem call will contain any old rubbish.
>>> The reference to LogData.LogArgs in the assignment may be
>>> dereferencing a non-zero pointer&   attempting to use whatever it
>>> contains.
>>>
>>> Cheers
>>>
>>>
>>> On 25/08/2011 11:40 a.m., David Moorhouse (DUG) wrote:
>>>> I have the following code snippet
>>>>
>>>> <code>
>>>> type
>>>>      PConstArray = ^TConstArray;
>>>>      TConstArray = array of TVarRec;
>>>>
>>>> function CreateConstArray(const Elements: array of const): TConstArray;
>>>>
>>>> type
>>>>      TLogType = (ltError, ltWarn, ltInfo);
>>>>      PLogData = ^TLogData;
>>>>      TLogData = record
>>>>        LogType: TLogType;
>>>>        LogArgs: TConstArray;
>>>>      end;
>>>>
>>>> ....
>>>>
>>>> procedure TUserClass.Log(const LogType: TLogType; const Args: array of
>>>> const );
>>>> var
>>>>      LogData: PLogData;
>>>> begin
>>>>        // size of record TLogData does not work
>>>>        GetMem(LogData, sizeof(TLogData));
>>>>        LogData.LogType := LogType;
>>>> // blows up on next line
>>>>        LogData.LogArgs := CreateConstArray(Args);
>>>> //  ... do some other stuff with the LogData item finally calling
>>>> FreeMem
>>>> end;
>>>>
>>>> function CreateConstArray(const Elements: array of const): TConstArray;
>>>> var
>>>>      I: Integer;
>>>> begin
>>>>      SetLength(Result, Length(Elements));
>>>>      for I := Low(Elements) to High(Elements) do
>>>>        Result[I] :=  // assign a TVarRec here
>>>> end;
>>>> </code>
>>>>
>>>> The code that assigns the memory only assigns 8 bytes - and an access
>>>> violation ensues.  If I replace the call to "sizeof" with the number 16,
>>>> the code works fine.
>>>>
>>>> My understanding of dynamic arrays was that the compiler created a 4
>>>> byte
>>>> field before the first element that contained the length of the array.
>>>>
>>>> So why does the sizeof  function not reflect this ?  And why do I
>>>> need 16
>>>> bytes not 12  (4 for LogType + 4 for length of array + 4 for array
>>>> pointer)?
>>>> Also regardless of the number of items in the open array parameter, 16
>>>> bytes works, so it does not relate the length of the TConstArray.
>>>>
>>>> Your thoughts ?
>>>>
>>>> David
>>>>
>>>>
>>>>
>>>> _______________________________________________
>>>> NZ Borland Developers Group - Delphi mailing list
>>>> Post: delphi@delphi.org.nz
>>>> Admin: http://delphi.org.nz/mailman/listinfo/delphi
>>>> Unsubscribe: send an email to delphi-requ...@delphi.org.nz with
>>>> Subject: unsubscribe
>>>>
>>
>> _______________________________________________
>> NZ Borland Developers Group - Delphi mailing list
>> Post: delphi@delphi.org.nz
>> Admin: http://delphi.org.nz/mailman/listinfo/delphi
>> Unsubscribe: send an email to delphi-requ...@delphi.org.nz with Subject: 
>> unsubscribe
>>
> _______________________________________________
> NZ Borland Developers Group - Delphi mailing list
> Post: delphi@delphi.org.nz
> Admin: http://delphi.org.nz/mailman/listinfo/delphi
> Unsubscribe: send an email to delphi-requ...@delphi.org.nz with Subject: 
> unsubscribe


_______________________________________________
NZ Borland Developers Group - Delphi mailing list
Post: delphi@delphi.org.nz
Admin: http://delphi.org.nz/mailman/listinfo/delphi
Unsubscribe: send an email to delphi-requ...@delphi.org.nz with Subject: 
unsubscribe

Reply via email to