<html>
  <head>
    <meta content="text/html; charset=UTF-8" http-equiv="Content-Type">
  </head>
  <body bgcolor="#FFFFFF" text="#000000">
    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 :)<br>
    <br>
    However, the compiler gets the size right using New rather than
    GetMem :) So thanks for the tip.<br>
    <br>
    Cheers<br>
    <br>
    D<br>
    <br>
    <br>
    <br>
    <br>
    On 29/08/11 16:23, Jolyon Smith wrote:
    <blockquote
cite="mid:CALXexOrQUzqG=+DvT+3U-SFrNZ3itgdH4_+-944B0ZJ8=HW4kA@mail.gmail.com"
      type="cite">Is it a compiler *error* or just a compiler
      _behaviour_ ?<br>
      <br>
      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.
      <div>
        <br>
      </div>
      <div>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).<br>
        <br>
        NOTE:   sizeof(String) also yields "4" even though we all know
        that a String variable requires many more bytes than that.</div>
      <div><br>
      </div>
      <div><br>
        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...:</div>
      <div><br>
      </div>
      <div>Instead of &gt;&gt;   LogData := GetMem( ... );      </div>
      <div><br>
      </div>
      <div>Use          &gt;&gt;   New( LogData );<br>
        <br>
        And see if you get better results.  :)<br>
        <br>
        (Also, don't forget to use "Dispose()" to deallocate the memory
        obtained with "New()", rather than FreeMem())<br>
        <br>
      </div>
      <div><br>
        <div class="gmail_quote">On 28 August 2011 21:33, David
          Moorhouse (DUG) <span dir="ltr">&lt;<a moz-do-not-send="true"
              href="mailto:delphi@moorhouse.net.nz">delphi@moorhouse.net.nz</a>&gt;</span>
          wrote:<br>
          <blockquote class="gmail_quote" style="margin:0 0 0
            .8ex;border-left:1px #ccc solid;padding-left:1ex;">
            I believe it is a compiler error and will raise a QA ticket<br>
            <br>
            Thanks for your  help<br>
            <font color="#888888"><br>
              <br>
              D<br>
            </font>
            <div>
              <div class="h5"><br>
                <br>
                On 26/08/11 08:17, Peter Ingham wrote:<br>
                &gt; Try filling LogData with binary zeros after the
                Getmem&amp;  before the assign.<br>
                &gt;<br>
                &gt; FillChar (LogData^, sizeof(TLogData), 0);<br>
                &gt;<br>
                &gt; I believe the uninitialized memory is messing up
                the compiler magic<br>
                &gt; associated with the dynamic array.<br>
                &gt;<br>
                &gt;<br>
                &gt; Any reason the local Tlogdata record is referenced
                via a pointer?<br>
                &gt;<br>
                &gt; I suspect the following will also work:<br>
                &gt; procedure TUserClass.Log(const LogType: TLogType;
                const Args: array of<br>
                &gt; const );<br>
                &gt;    var<br>
                &gt;       LogData: TLogData;<br>
                &gt;     begin<br>
                &gt;       LogData.LogType := LogType;<br>
                &gt;       LogData.LogArgs := CreateConstArray(Args);<br>
                &gt;       //  ... do some other stuff with the LogData
                item finally calling<br>
                &gt;     end;<br>
                &gt;<br>
                &gt; Cheers<br>
                &gt;<br>
                &gt; On 26/08/2011 1:49 a.m., David Moorhouse wrote:<br>
                &gt;&gt; Hi Peter<br>
                &gt;&gt;<br>
                &gt;&gt; Been there done that :)<br>
                &gt;&gt;<br>
                &gt;&gt; The function call is fine.  It is the
                assignment that causes the AV -<br>
                &gt;&gt; because the "bucket" is too small.<br>
                &gt;&gt; Assigning it with 16 bytes fixes the problem,
                regardless of how many<br>
                &gt;&gt; items the array holds.<br>
                &gt;&gt;<br>
                &gt;&gt; I smell compiler magic in the background.<br>
                &gt;&gt;<br>
                &gt;&gt; Cheers<br>
                &gt;<br>
                &gt;&gt; D<br>
                &gt;&gt;<br>
                &gt;&gt; On 25/08/11 17:29, Peter Ingham wrote:<br>
                &gt;&gt;&gt; Another attempt to reply...<br>
                &gt;&gt;&gt;<br>
                &gt;&gt;&gt; First thing to do is determine if the crash
                occurs in the procedure call,<br>
                &gt;&gt;&gt; on the subsequent assign, or in between.<br>
                &gt;&gt;&gt;<br>
                &gt;&gt;&gt; Give this a try:<br>
                &gt;&gt;&gt;    procedure TUserClass.Log(const LogType:
                TLogType; const Args: array of<br>
                &gt;&gt;&gt;    const );<br>
                &gt;&gt;&gt;    var<br>
                &gt;&gt;&gt;      LogData: PLogData;<br>
                &gt;&gt;&gt;     TempArgs : TConstArray;<br>
                &gt;&gt;&gt;    begin<br>
                &gt;&gt;&gt;        // size of record TLogData does not
                work<br>
                &gt;&gt;&gt;        GetMem(LogData, sizeof(TLogData));<br>
                &gt;&gt;&gt;        LogData.LogType := LogType;<br>
                &gt;&gt;&gt;    // blows up on one of these lines<br>
                &gt;&gt;&gt;        TempArgs  := CreateConstArray(Args);<br>
                &gt;&gt;&gt;        LogData.LogArgs := TempArgs;<br>
                &gt;&gt;&gt;    //  ... do some other stuff with the
                LogData item finally calling<br>
                &gt;&gt;&gt; FreeMem<br>
                &gt;&gt;&gt;    end;<br>
                &gt;&gt;&gt;<br>
                &gt;&gt;&gt;<br>
                &gt;&gt;&gt; Regarding the size of a dynamic array,
                 like a string variable,  the<br>
                &gt;&gt;&gt; variable (LogArgs in this case) is the size
                of a pointer (i.e. 4 bytes<br>
                &gt;&gt;&gt; for Win32).  If the pointer is non-zero, it
                points to a structure which<br>
                &gt;&gt;&gt; includes the adjacent array elements
                preceded by a length.<br>
                &gt;&gt;&gt;<br>
                &gt;&gt;&gt; One thing to watch out for is that Getmem
                does not clear the allocated<br>
                &gt;&gt;&gt; memory, so LogData after the Getmem call
                will contain any old rubbish.<br>
                &gt;&gt;&gt; The reference to LogData.LogArgs in the
                assignment may be<br>
                &gt;&gt;&gt; dereferencing a non-zero pointer&amp;  
                attempting to use whatever it<br>
                &gt;&gt;&gt; contains.<br>
                &gt;&gt;&gt;<br>
                &gt;&gt;&gt; Cheers<br>
                &gt;&gt;&gt;<br>
                &gt;&gt;&gt;<br>
                &gt;&gt;&gt; On 25/08/2011 11:40 a.m., David Moorhouse
                (DUG) wrote:<br>
                &gt;&gt;&gt;&gt; I have the following code snippet<br>
                &gt;&gt;&gt;&gt;<br>
                &gt;&gt;&gt;&gt; &lt;code&gt;<br>
                &gt;&gt;&gt;&gt; type<br>
                &gt;&gt;&gt;&gt;      PConstArray = ^TConstArray;<br>
                &gt;&gt;&gt;&gt;      TConstArray = array of TVarRec;<br>
                &gt;&gt;&gt;&gt;<br>
                &gt;&gt;&gt;&gt; function CreateConstArray(const
                Elements: array of const): TConstArray;<br>
                &gt;&gt;&gt;&gt;<br>
                &gt;&gt;&gt;&gt; type<br>
                &gt;&gt;&gt;&gt;      TLogType = (ltError, ltWarn,
                ltInfo);<br>
                &gt;&gt;&gt;&gt;      PLogData = ^TLogData;<br>
                &gt;&gt;&gt;&gt;      TLogData = record<br>
                &gt;&gt;&gt;&gt;        LogType: TLogType;<br>
                &gt;&gt;&gt;&gt;        LogArgs: TConstArray;<br>
                &gt;&gt;&gt;&gt;      end;<br>
                &gt;&gt;&gt;&gt;<br>
                &gt;&gt;&gt;&gt; ....<br>
                &gt;&gt;&gt;&gt;<br>
                &gt;&gt;&gt;&gt; procedure TUserClass.Log(const LogType:
                TLogType; const Args: array of<br>
                &gt;&gt;&gt;&gt; const );<br>
                &gt;&gt;&gt;&gt; var<br>
                &gt;&gt;&gt;&gt;      LogData: PLogData;<br>
                &gt;&gt;&gt;&gt; begin<br>
                &gt;&gt;&gt;&gt;        // size of record TLogData does
                not work<br>
                &gt;&gt;&gt;&gt;        GetMem(LogData,
                sizeof(TLogData));<br>
                &gt;&gt;&gt;&gt;        LogData.LogType := LogType;<br>
                &gt;&gt;&gt;&gt; // blows up on next line<br>
                &gt;&gt;&gt;&gt;        LogData.LogArgs :=
                CreateConstArray(Args);<br>
                &gt;&gt;&gt;&gt; //  ... do some other stuff with the
                LogData item finally calling<br>
                &gt;&gt;&gt;&gt; FreeMem<br>
                &gt;&gt;&gt;&gt; end;<br>
                &gt;&gt;&gt;&gt;<br>
                &gt;&gt;&gt;&gt; function CreateConstArray(const
                Elements: array of const): TConstArray;<br>
                &gt;&gt;&gt;&gt; var<br>
                &gt;&gt;&gt;&gt;      I: Integer;<br>
                &gt;&gt;&gt;&gt; begin<br>
                &gt;&gt;&gt;&gt;      SetLength(Result,
                Length(Elements));<br>
                &gt;&gt;&gt;&gt;      for I := Low(Elements) to
                High(Elements) do<br>
                &gt;&gt;&gt;&gt;        Result[I] :=  // assign a
                TVarRec here<br>
                &gt;&gt;&gt;&gt; end;<br>
                &gt;&gt;&gt;&gt; &lt;/code&gt;<br>
                &gt;&gt;&gt;&gt;<br>
                &gt;&gt;&gt;&gt; The code that assigns the memory only
                assigns 8 bytes - and an access<br>
                &gt;&gt;&gt;&gt; violation ensues.  If I replace the
                call to "sizeof" with the number 16,<br>
                &gt;&gt;&gt;&gt; the code works fine.<br>
                &gt;&gt;&gt;&gt;<br>
                &gt;&gt;&gt;&gt; My understanding of dynamic arrays was
                that the compiler created a 4<br>
                &gt;&gt;&gt;&gt; byte<br>
                &gt;&gt;&gt;&gt; field before the first element that
                contained the length of the array.<br>
                &gt;&gt;&gt;&gt;<br>
                &gt;&gt;&gt;&gt; So why does the sizeof  function not
                reflect this ?  And why do I<br>
                &gt;&gt;&gt;&gt; need 16<br>
                &gt;&gt;&gt;&gt; bytes not 12  (4 for LogType + 4 for
                length of array + 4 for array<br>
                &gt;&gt;&gt;&gt; pointer)?<br>
                &gt;&gt;&gt;&gt; Also regardless of the number of items
                in the open array parameter, 16<br>
                &gt;&gt;&gt;&gt; bytes works, so it does not relate the
                length of the TConstArray.<br>
                &gt;&gt;&gt;&gt;<br>
                &gt;&gt;&gt;&gt; Your thoughts ?<br>
                &gt;&gt;&gt;&gt;<br>
                &gt;&gt;&gt;&gt; David<br>
                &gt;&gt;&gt;&gt;<br>
                &gt;&gt;&gt;&gt;<br>
                &gt;&gt;&gt;&gt;<br>
                &gt;&gt;&gt;&gt;
                _______________________________________________<br>
                &gt;&gt;&gt;&gt; NZ Borland Developers Group - Delphi
                mailing list<br>
                &gt;&gt;&gt;&gt; Post: <a moz-do-not-send="true"
                  href="mailto:delphi@delphi.org.nz">delphi@delphi.org.nz</a><br>
                &gt;&gt;&gt;&gt; Admin: <a moz-do-not-send="true"
                  href="http://delphi.org.nz/mailman/listinfo/delphi"
                  target="_blank">http://delphi.org.nz/mailman/listinfo/delphi</a><br>
                &gt;&gt;&gt;&gt; Unsubscribe: send an email to <a
                  moz-do-not-send="true"
                  href="mailto:delphi-request@delphi.org.nz">delphi-request@delphi.org.nz</a>
                with<br>
                &gt;&gt;&gt;&gt; Subject: unsubscribe<br>
                &gt;&gt;&gt;&gt;<br>
                &gt;&gt;<br>
                &gt;&gt; _______________________________________________<br>
                &gt;&gt; NZ Borland Developers Group - Delphi mailing
                list<br>
                &gt;&gt; Post: <a moz-do-not-send="true"
                  href="mailto:delphi@delphi.org.nz">delphi@delphi.org.nz</a><br>
                &gt;&gt; Admin: <a moz-do-not-send="true"
                  href="http://delphi.org.nz/mailman/listinfo/delphi"
                  target="_blank">http://delphi.org.nz/mailman/listinfo/delphi</a><br>
                &gt;&gt; Unsubscribe: send an email to <a
                  moz-do-not-send="true"
                  href="mailto:delphi-request@delphi.org.nz">delphi-request@delphi.org.nz</a>
                with Subject: unsubscribe<br>
                &gt;&gt;<br>
                &gt; _______________________________________________<br>
                &gt; NZ Borland Developers Group - Delphi mailing list<br>
                &gt; Post: <a moz-do-not-send="true"
                  href="mailto:delphi@delphi.org.nz">delphi@delphi.org.nz</a><br>
                &gt; Admin: <a moz-do-not-send="true"
                  href="http://delphi.org.nz/mailman/listinfo/delphi"
                  target="_blank">http://delphi.org.nz/mailman/listinfo/delphi</a><br>
                &gt; Unsubscribe: send an email to <a
                  moz-do-not-send="true"
                  href="mailto:delphi-request@delphi.org.nz">delphi-request@delphi.org.nz</a>
                with Subject: unsubscribe<br>
                <br>
                <br>
                _______________________________________________<br>
                NZ Borland Developers Group - Delphi mailing list<br>
                Post: <a moz-do-not-send="true"
                  href="mailto:delphi@delphi.org.nz">delphi@delphi.org.nz</a><br>
                Admin: <a moz-do-not-send="true"
                  href="http://delphi.org.nz/mailman/listinfo/delphi"
                  target="_blank">http://delphi.org.nz/mailman/listinfo/delphi</a><br>
                Unsubscribe: send an email to <a moz-do-not-send="true"
                  href="mailto:delphi-request@delphi.org.nz">delphi-request@delphi.org.nz</a>
                with Subject: unsubscribe<br>
                <br>
              </div>
            </div>
          </blockquote>
        </div>
        <br>
      </div>
    </blockquote>
    <br>
  </body>
</html>