[DUG] [computing] Sizeof record gives error
David Moorhouse (DUG)
delphi at moorhouse.net.nz
Sun Aug 28 21:33:43 NZST 2011
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 at delphi.org.nz
>>>> Admin: http://delphi.org.nz/mailman/listinfo/delphi
>>>> Unsubscribe: send an email to delphi-request at delphi.org.nz with
>>>> Subject: unsubscribe
>>>>
>>
>> _______________________________________________
>> NZ Borland Developers Group - Delphi mailing list
>> Post: delphi at delphi.org.nz
>> Admin: http://delphi.org.nz/mailman/listinfo/delphi
>> Unsubscribe: send an email to delphi-request at delphi.org.nz with Subject: unsubscribe
>>
> _______________________________________________
> NZ Borland Developers Group - Delphi mailing list
> Post: delphi at delphi.org.nz
> Admin: http://delphi.org.nz/mailman/listinfo/delphi
> Unsubscribe: send an email to delphi-request at delphi.org.nz with Subject: unsubscribe
More information about the Delphi
mailing list