Re: [DUG] [computing] Sizeof record gives error
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
Re: [DUG] [computing] Sizeof record gives error
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
Re: [DUG] [computing] Sizeof record gives error
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
Re: [DUG] [computing] Sizeof record gives error
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