Re: [DUG] [computing] Sizeof record gives error

2011-08-28 Thread David Moorhouse (DUG)
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

2011-08-25 Thread David Moorhouse
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

2011-08-25 Thread Peter Ingham
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

2011-08-24 Thread Peter Ingham
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