Announcement

Collapse
No announcement yet.

allozierten Speicherbereich einer dynamischen Variable ermitteln

Collapse
X
  • Filter
  • Time
  • Show
Clear All
new posts

  • allozierten Speicherbereich einer dynamischen Variable ermitteln

    Hallo,

    wie kann ich ermitteln wie groß der Speicherbereich ist der einer dynamischen Variable zugeordnet wurde?

    Tschüß

    Torsten

  • #2
    Length(Arr) * SizeOf(Arr[0])

    Gruß Nico

    PS: <i>dynamische Arrays sind intern Pointer (nil = []); sie zeigen auf den Beginn des ersten Elements; davor steht ein Header mit Anzahl/Größe der Elemente, etc (Warnung: Nutzung dieses Wissens ist compiler-spezifisch, zudem kümmert sich Delphi selbst um die Arrays (sollte man sich nicht einmischen...))</i&gt

    Comment


    • #3
      Hallo Nico,

      das hilft mir noch nicht weiter. Wenn ich mit ReAllocMem die Größe des reservierten Speichers ändere bleiben die bisherigen Daten vorhanden, allerdings wird der "zusätzlich" reservierte Speicher nicht mit 0 initialisiert (was ich aber unbedingt benötige). Deshalb möchte ich mir eine allgemeingültige Procedure schreiben die das gleich intern mit erledigt. Als Parameter wollte ich nur die Variable sowie die neue Speichergröße angeben.

      Tschüß

      Torste

      Comment


      • #4
        Hi

        <pre>

        procedure ReallocMemZero(var P: Pointer; Size: Integer);
        var
        SizeFlags: Integer;
        begin
        if (P <> nil) and (Size > 0) then
        begin
        SizeFlags := PInteger(PChar(P) -4)^ and not 3;
        ReallocMem(P, Size);
        if Size > SizeFlags then
        FillChar(PByteArray(P)[Size], Size - SizeFlags, 0);
        end else ReallocMem(P, Size);
        end;

        </pre>

        Beachte aber das diese Funktion NUR mit dem Borland MM funktionieren kann, da dieser die aktuelle Große in den 4 Bytes vor dem eigentlichen Pointer verwaltet. Andere benutzer installierte MM's können dies auf andere Weise verwalten.

        Gruß hagen

        PS: above source isn't tested yet :

        Comment


        • #5
          Hallo Hagen,

          erst einmal vielen Dank. Die Berechnung der Größe stimmt nicht ganz. Zusätzlich muß noch der Header(4 Byte) abgezogen werden. Also <b>SizeFlags := PInteger(PChar(P) -4)^ and not 3 - 4;</b>.

          Die zwei niederwertigsten Bits sind vermutlich Flags. Weißt Du auch was man ihnen entnehmen kann?

          Tschüß

          Torste

          Comment


          • #6
            Nein, die Funktion schient richtig zu sein,

            Da der Delphi-MM immer mindestens 4 Bytes (DWORD) anfordert.<br>
            Der Quellcode prüft (unter Ausblendung der unteren Bits 0 und 1) ob der neue Speicherbereich größer ist und initialisiert den neuen Bereich...

            Gruß Nico
            &#10

            Comment


            • #7
              apropos (habe gerade kein Delphi da,,,)

              Mir ist so, als ob man beim MemoryManager die HeapFlags angeben kann (wie wäre es dann mit ZERO_INIT... kann nicht mal jemand nachsehen =)

              Gruß Nic

              Comment


              • #8
                Hallo Nico,

                der Tip mit den HeapFlags ist der allereinfachste Weg. Ich muß nur das Flag GMEM_ZEROINIT setzen.

                Bei meinen praktischen Test's mit der Funktion von Hagen ist das Ergebnis der Speichergröße immer um 4 Byte größer gewesen als der zuvor angeforderte Speicher.

                Tschüß

                Torste

                Comment


                • #9
                  Hallo Nico,

                  man soll den Tag nicht vor dem Abend loben. Leider scheint sich Delphi oder WinNT4.0 nicht nach dem Flag zu richten. Ich tippe mal auf Delphi, weil bei der Funktion AllocMem extra noch der Speicher mit FillChar auf 0 gesetzt wird.

                  Tschüß

                  Torste

                  Comment


                  • #10
                    Hi

                    @Torsten, richtig die 4 Bytes des SizeFlags selber müssen abgezogen werden, oder umgekehrt zur übergebenen Size addiert werden. Eines von beiden, da SizeFlag eben intern den kompletten Block darstellt, damit IST SizeFlags auch ein verketteter zeiger auf den nächsten Block.<br> Sorry, war eben mal schnell in's Forum gehackt <br>
                    Die untersten Flags kannste in GetMem.inc nachschlagen, cThisUsedFlag = 2 und cPrevFreeFlag = 1. wobei mit cThisUsedFlag überprüft werden kann ob ein Block gerade benutzt = alloziert ist.<br>

                    @Nico: Das Flag wird zwar vom NT/Win benutzt und auch ausgeführt, ABER Delphi legt in den freiem preallozierten Speicher seine MM Verwaltungsinfos an, siehe Mem.inc->TFree. D.h. nach vielen Reallozierungen entsteht Fragmentation, und jedes freie Fragment ist über die ersten 8 bytes ! als Header verknüpft mit dem nächsten freien Block. Werden durch den MM mehrere nachfolgende freie Blöcke zu einem großen freien Block vereint, bleiben die ehemaligen TFree Strukturen im Speicher stehen.<br>
                    Die 8 Bytes sind logisch, 4 sind Minimum für SizeFlags + 4 für die minimale allozierte Größe, heist im ungenutzten Zustand eines Blockes = TFree können 8 Bytes für den MM als Verwaltungsinformation genutzt werden. Die zusätzlichen 4 bytes sind ein "zeiger" auf den nächsten Block (falls ich mich richtig erinnere).<br>

                    Für mein DEC stand ich vor ähnlichen Problemen um ihn für Sicherheitsanwendungen annehmbar umzustricken. Als Endresultat kann ich nur sagen das ein "Drum-Herum basteln" aussichtslos ist. Und so musste ich direkt den originale getMem.inc becleanen und direkt die basis modifizieren. Dabei zeigte sich das im Borland MM meiner Meinung nach noch einige logische und auch offensichtliche fehler stecken. Auch die Modifizierung des MM zu einem echt threadsafen MM ohne CS's wäre eigentlich ohne viel Aufwand möglich. Nun, mein überarbeiteter MM ist ca. 2 mal schneller OHNE wesentliche Änderungen am Design, einfach nur durch das bessere Tuning an 32 Bit Systeme und an die eigenheiten der Borland PASCAL Compiler. Leider ist der Borland MM schon in die Jahre gekommen, keiner bei Borland traut oder wagt es ihn mal upzudaten und offensichtlich war der Programmer des MM's KEIN pascal sondern C coder. Auf alle fälle lässt sich z.b. der MM erweitern um solche heut wichtigen Features wie aligned Memory Blocks, oder die generelle Ausrichtung an 16/32 Byte Grenzen. Alleine das verspricht im Durchschnitt schon ein Speedzuwachs von 200% !! (gesamtlaufzeit der Anwendung, wohlgemerkt)

                    Gruß Hage

                    Comment


                    • #11
                      Hallo Hagen,

                      ist kein Problem, normalerweise reicht mir auch die grobe Richtung zur Problemlösung. Den Rest bastele ich mir dann schon zusammen. An Deinem Beispiel habe ich eh noch ein bisschen geändert. So wird z.B. getestet ob der Borland Memory-Manager verwendet wird.

                      Schönes Wochenende

                      Torste

                      Comment


                      • #12
                        Wie ? reposte doch den Code

                        Comment


                        • #13
                          Hallo Hagen,

                          <pre><b>
                          procedure ReallocMemZero(var P: Pointer; Size: Integer);
                          var
                          SizeFlags: Integer;
                          type
                          PInteger = ^Integer;
                          begin
                          if IsMemoryManagerSet then begin
                          MessageBox(0, PChar('Fehler'), PChar('Das Programm verwendet nicht den Borland-Memory Manager'), mb_iconerror + mb_ok);
                          halt; </b> zwar brutal ist ja aber auch nur zur Sicherheit eingebaut, falls ich mal einen anderen MM verwende und dann nicht mehr an diese Funktion denke<b>
                          end;
                          if (P <> nil) and (Size > 0) then begin
                          SizeFlags := PInteger(PChar(P) -4)^ and not 3 - 4;
                          ReallocMem(P, Size);
                          if Size > SizeFlags then FillChar(PByteArray(P)[SizeFlags], Size - SizeFlags, 0);
                          end
                          else begin
                          if (p = nil) and (Size > 0) then P := AllocMem(Size)
                          else ReallocMem(P, Size);
                          end;
                          end;
                          </pre></b>

                          Tschüß

                          Torsten

                          PS: wenn ich mich richtig erinnere hast Du Dich vor längerer Zeit hier im Forum oder den Vorgänger-Foren mal sehr positiv zum Borland Memory Manager geäußert. Heute klingt das nicht mehr so

                          Comment


                          • #14
                            Hm, JAIN.

                            Der Borland MM IST der mir bekanntermaßen beste MM für Anwendungen die sehr viele kleine, viele mittlere und wenige große Allozierungen benötigen. Zudem muß man bedenken der aktuelle MM von D6 schon in 16Bit DOS Pascal Versionen enthalten war. d.h. der heute benutzte MM unterscheidet sich NICHT wesentlich vom MM in Borland Pascal 4 z.b.
                            Diese "Potenz" sieht man nicht oft bei MM's.
                            ABER, die Zeiten ändern sich, und so ist der heutige MM beim Thema Multithreading, Alignment, Debugging, Security, Protection und Tracing nicht mehr auf dem aktuellsten Stand.<br>

                            Fazit: Ich meine immer noch das der MM sehr gut ist, das hindert aber nicht daran auch mal einen kritischen Blick zu riskieren und mal nach Rechts und Links zu schauen )<br>

                            Gruß hage

                            Comment


                            • #15
                              Achso, hab ich ganz vergessen. Mein Frage nach Deinem Quelltext hatte einen ganz bestimmten Grund. Nun, so wie Du das angepackt hast tritt genau das ein was ich vermutet hatte. Deine Änderung wird NICHT in DLL's die SharedMem benutzen funktionieren. Im grunde gibts nämlich keine saubere Lösung zur Erkennung des benutzten MM's. Auch ein möglicher Kritikpunkt am MM.

                              gruß hage

                              Comment

                              Working...
                              X