[DUG] [computing] Sizeof record gives error
Rohit Gupta
rohit at cfl.co.nz
Tue Aug 30 09:10:19 NZST 2011
Joylon,
Good point. But I dont think it applies here. Sizeof returns an
incorrect result... Its a compiler flaw.
Rohit
On 29/08/2011 8:10 p.m., Jolyon Smith wrote:
> Having just looked up the references for New/GetMem it may not
> actually be a question of amount of memory allocated after all, but
> rather one of correct initialization of the allocated memory.
>
> GetMem() does not initialize the allocated memory, New() does.
>
> This is explained in the documentation for the "Initialize()"
> procedure (it might have been helpful if the documentation for
> GetMem() had mentioned this - or the lack there-of - too - LOL)
>
> So you might find that GetMem() would have worked had you also called
> Initialise() on the pointer afterward (and Finalize() before calling
> FreeMem()). But whatever the underlying reasons it is obviously
> simply much easier and safer (less to remember to have to do, less to
> get wrong in doing it :)) to use New/Dispose when working with
> allocations of variables/structured(typed) memory and use
> GetMem/FreeMem when it is strictly speaking *just* unstructured memory
> you need (e.g. i/o buffers etc), rather than space for variables.
>
> Glad it helped with your problem in any event. :)
>
>
> On 29 August 2011 17:40, David Moorhouse <delphi at moorhouse.net.nz
> <mailto:delphi at moorhouse.net.nz>> wrote:
>
> I'm aware of the compiler layout behind the scene - and the fact
> that regardless of the length of the dynamic array, my call to
> GetMem (or New) does NOT have to allocate memory for the dynamic
> array's contents, just it's overhead :)
>
> However, the compiler gets the size right using New rather than
> GetMem :) So thanks for the tip.
>
> Cheers
>
> D
>
>
>
>
>
> On 29/08/11 16:23, Jolyon Smith wrote:
>> Is it a compiler *error* or just a compiler _behaviour_ ?
>>
>> I haven't looked into it in detail, but dynamic arrays are
>> notoriously slippery when you are working with them at a low
>> level and alarm bells started ringing as soon as I saw they were
>> involved.
>>
>> In particular, a dynamic array is a reference type, like a
>> string. So whilst their may be additional RTTI at a negative
>> offset from the base address of the array, the "array" itself may
>> well be a pointer, hence "sizeof()" will return 4 - the size of a
>> pointer - no matter how many items may be in the array (as
>> opposed to Length(), obviously).
>>
>> NOTE: sizeof(String) also yields "4" even though we all know
>> that a String variable requires many more bytes than that.
>>
>>
>> As far as this particular example goes, do you get any better
>> results using the typed New() function rather than GetMem() which
>> knows nothing about the "type" of memory required by the pointer
>> you are initialising and just blithely allocates the specified
>> number of bytes...:
>>
>> Instead of >> LogData := GetMem( ... );
>>
>> Use >> New( LogData );
>>
>> And see if you get better results. :)
>>
>> (Also, don't forget to use "Dispose()" to deallocate the memory
>> obtained with "New()", rather than FreeMem())
>>
>>
>> On 28 August 2011 21:33, David Moorhouse (DUG)
>> <delphi at moorhouse.net.nz <mailto:delphi at moorhouse.net.nz>> wrote:
>>
>> 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
>> >>>>
>> >>>>
>>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: http://listserver.123.net.nz/pipermail/delphi/attachments/20110830/56e2dbba/attachment-0001.html
More information about the Delphi
mailing list