<html>
  <head>
    <meta content="text/html; charset=ISO-8859-1"
      http-equiv="Content-Type">
  </head>
  <body bgcolor="#FFFFFF" text="#000000">
    Joylon,<br>
    <br>
    Good point.&nbsp; But I dont think it applies here.&nbsp; Sizeof returns an
    incorrect result... Its a compiler flaw.<br>
    <br>
    Rohit<br>
    <br>
    <br>
    <br>
    On 29/08/2011 8:10 p.m., Jolyon Smith wrote:
    <blockquote
cite="mid:CALXexOoYWOaQ1myKaY47cVL-S5e0b8aqGQAL_xdQf=ZNRb29TA@mail.gmail.com"
      type="cite">
      <div>
        <div>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.</div>
        <div><br>
        </div>
        <div>GetMem() does not initialize the allocated memory, New()
          does.</div>
        <div><br>
        </div>
        <div>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)</div>
        <div><br>
        </div>
        <div>So you might find that GetMem() would have worked had you
          also called Initialise() on the pointer afterward (and
          Finalize() before calling FreeMem()). &nbsp;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.<br>
          <br>
          Glad it helped with your problem in any event. &nbsp;:)</div>
        <div><br>
        </div>
        <div><br>
          <div class="gmail_quote">On 29 August 2011 17:40, David
            Moorhouse <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;">
              <div 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>
                <font color="#888888"> <br>
                  D</font>
                <div>
                  <div class="h5"><br>
                    <br>
                    <br>
                    <br>
                    <br>
                    On 29/08/11 16:23, Jolyon Smith wrote:
                    <blockquote 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. &nbsp;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: &nbsp; 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; &nbsp; LogData := GetMem( ...
                        ); &nbsp; &nbsp; &nbsp;</div>
                      <div><br>
                      </div>
                      <div>Use &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&gt;&gt; &nbsp; New( LogData );<br>
                        <br>
                        And see if you get better results. &nbsp;:)<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"
                              target="_blank">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 &nbsp;help<br>
                            <font color="#888888"><br>
                              <br>
                              D<br>
                            </font>
                            <div>
                              <div><br>
                                <br>
                                On 26/08/11 08:17, Peter Ingham wrote:<br>
                                &gt; Try filling LogData with binary
                                zeros after the Getmem&amp; &nbsp;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; &nbsp; &nbsp;var<br>
                                &gt; &nbsp; &nbsp; &nbsp; LogData: TLogData;<br>
                                &gt; &nbsp; &nbsp; begin<br>
                                &gt; &nbsp; &nbsp; &nbsp; LogData.LogType := LogType;<br>
                                &gt; &nbsp; &nbsp; &nbsp; LogData.LogArgs :=
                                CreateConstArray(Args);<br>
                                &gt; &nbsp; &nbsp; &nbsp; // &nbsp;... do some other stuff
                                with the LogData item finally calling<br>
                                &gt; &nbsp; &nbsp; 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. &nbsp;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; &nbsp; &nbsp;procedure
                                TUserClass.Log(const LogType: TLogType;
                                const Args: array of<br>
                                &gt;&gt;&gt; &nbsp; &nbsp;const );<br>
                                &gt;&gt;&gt; &nbsp; &nbsp;var<br>
                                &gt;&gt;&gt; &nbsp; &nbsp; &nbsp;LogData: PLogData;<br>
                                &gt;&gt;&gt; &nbsp; &nbsp; TempArgs : TConstArray;<br>
                                &gt;&gt;&gt; &nbsp; &nbsp;begin<br>
                                &gt;&gt;&gt; &nbsp; &nbsp; &nbsp; &nbsp;// size of record
                                TLogData does not work<br>
                                &gt;&gt;&gt; &nbsp; &nbsp; &nbsp; &nbsp;GetMem(LogData,
                                sizeof(TLogData));<br>
                                &gt;&gt;&gt; &nbsp; &nbsp; &nbsp; &nbsp;LogData.LogType :=
                                LogType;<br>
                                &gt;&gt;&gt; &nbsp; &nbsp;// blows up on one of
                                these lines<br>
                                &gt;&gt;&gt; &nbsp; &nbsp; &nbsp; &nbsp;TempArgs &nbsp;:=
                                CreateConstArray(Args);<br>
                                &gt;&gt;&gt; &nbsp; &nbsp; &nbsp; &nbsp;LogData.LogArgs :=
                                TempArgs;<br>
                                &gt;&gt;&gt; &nbsp; &nbsp;// &nbsp;... do some other
                                stuff with the LogData item finally
                                calling<br>
                                &gt;&gt;&gt; FreeMem<br>
                                &gt;&gt;&gt; &nbsp; &nbsp;end;<br>
                                &gt;&gt;&gt;<br>
                                &gt;&gt;&gt;<br>
                                &gt;&gt;&gt; Regarding the size of a
                                dynamic array, &nbsp;like a string variable,
                                &nbsp;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). &nbsp;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; &nbsp; 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; &nbsp; &nbsp; &nbsp;PConstArray =
                                ^TConstArray;<br>
                                &gt;&gt;&gt;&gt; &nbsp; &nbsp; &nbsp;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; &nbsp; &nbsp; &nbsp;TLogType =
                                (ltError, ltWarn, ltInfo);<br>
                                &gt;&gt;&gt;&gt; &nbsp; &nbsp; &nbsp;PLogData =
                                ^TLogData;<br>
                                &gt;&gt;&gt;&gt; &nbsp; &nbsp; &nbsp;TLogData = record<br>
                                &gt;&gt;&gt;&gt; &nbsp; &nbsp; &nbsp; &nbsp;LogType:
                                TLogType;<br>
                                &gt;&gt;&gt;&gt; &nbsp; &nbsp; &nbsp; &nbsp;LogArgs:
                                TConstArray;<br>
                                &gt;&gt;&gt;&gt; &nbsp; &nbsp; &nbsp;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; &nbsp; &nbsp; &nbsp;LogData: PLogData;<br>
                                &gt;&gt;&gt;&gt; begin<br>
                                &gt;&gt;&gt;&gt; &nbsp; &nbsp; &nbsp; &nbsp;// size of
                                record TLogData does not work<br>
                                &gt;&gt;&gt;&gt; &nbsp; &nbsp; &nbsp; &nbsp;GetMem(LogData,
                                sizeof(TLogData));<br>
                                &gt;&gt;&gt;&gt; &nbsp; &nbsp; &nbsp; &nbsp;LogData.LogType
                                := LogType;<br>
                                &gt;&gt;&gt;&gt; // blows up on next
                                line<br>
                                &gt;&gt;&gt;&gt; &nbsp; &nbsp; &nbsp; &nbsp;LogData.LogArgs
                                := CreateConstArray(Args);<br>
                                &gt;&gt;&gt;&gt; // &nbsp;... 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; &nbsp; &nbsp; &nbsp;I: Integer;<br>
                                &gt;&gt;&gt;&gt; begin<br>
                                &gt;&gt;&gt;&gt; &nbsp; &nbsp; &nbsp;SetLength(Result,
                                Length(Elements));<br>
                                &gt;&gt;&gt;&gt; &nbsp; &nbsp; &nbsp;for I :=
                                Low(Elements) to High(Elements) do<br>
                                &gt;&gt;&gt;&gt; &nbsp; &nbsp; &nbsp; &nbsp;Result[I] := &nbsp;//
                                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. &nbsp;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
                                &nbsp;function not reflect this ? &nbsp;And why do
                                I<br>
                                &gt;&gt;&gt;&gt; need 16<br>
                                &gt;&gt;&gt;&gt; bytes not 12 &nbsp;(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>
                              </div>
                            </div>
                          </blockquote>
                        </div>
                      </div>
                    </blockquote>
                  </div>
                </div>
              </div>
            </blockquote>
          </div>
        </div>
      </div>
    </blockquote>
    <br>
  </body>
</html>