Heim  >  Artikel  >  Backend-Entwicklung  >  Wie ordnet C Objekte im Speicher an und was bedeutet das für die dynamische Umwandlung und Neuinterpretation?

Wie ordnet C Objekte im Speicher an und was bedeutet das für die dynamische Umwandlung und Neuinterpretation?

DDD
DDDOriginal
2024-11-02 03:52:30307Durchsuche

How does C   arrange objects in memory, and what does it mean for dynamic casting and reinterpreting?

Speicherlayout von C-Objekten

Frage:

Wie ist C im Speicher angeordnet? Objekt? Ich habe gehört, dass die dynamische Umwandlung nur den Zeiger des Objekts im Speicher anpasst, während die Neuinterpretation es uns ermöglicht, jede Operation an diesem Zeiger durchzuführen. Ich verstehe es nicht ganz. Bitte Angaben machen!

Antwort:

Speicherlayout

Speicherlayout hängt hauptsächlich von der Implementierung ab. Es gibt eine wichtige Ausnahme: Mitgliedsvariablen mit demselben Zugriffsspezifizierer werden in der Deklarationsreihenfolge angeordnet.

§ 9.2.14

非静态数据成员(非联合)具有相同访问控制权的类(Clause 11)被分配,以便后续成员在类对象中具有更高的地址。具有不同访问控制权的非静态数据成员的分配顺序未指定(11)。实现对齐要求可能导致两个相邻成员不会立即相互分配;管理虚拟函数(10.3)和虚拟基类(10.1)的空间要求也可能导致这种情况。

Andere Speicherverwaltung

Zusätzlich zu Mitgliedsvariablen muss eine Klasse oder Struktur auch Mitgliedsvariablen, Unterobjekte der Basisklasse und virtuell verwalten Funktionen (z. B. virtuelle Tabelle) und der für das Auffüllen und Ausrichten dieser Daten bereitgestellte Platz. Es hängt von der Implementierung ab, aber die Itanium ABI-Spezifikation ist eine beliebte Wahl. gcc und clang folgen ihm (zumindest teilweise).

http://mentorembedded.github.io/cxx-abi/abi.html#layout

Itanium ABI

Selbstverständlich ist das Itanium ABI nicht Teil des C-Standards und nicht verbindlich. Ausführlichere Informationen finden Sie in der Dokumentation und den Tools des Implementierers. clang bietet ein Tool zum Anzeigen des Speicherlayouts einer Klasse. Zum Beispiel Folgendes:

class VBase {
    virtual void corge();
    int j;
};

class SBase1 {
    virtual void grault();
    int k;
};

class SBase2 {
    virtual void grault();
    int k;
};

class SBase3 {
    void grault();
    int k;
};

class Class : public SBase1, SBase2, SBase3, virtual VBase {
public:
    void bar();
    virtual void baz();
    // 不允许虚拟成员函数模板,原因考虑内存布局和虚表
    // template<typename T>
    // virtual void quux();
private:
    int i;
    char c;
public:
    float f;
private:
    double d;
public:
    short s;
};

class Derived : public Class {
    virtual void qux();
};

int main() {
    return sizeof(Derived);
}

Nachdem Sie eine Quelldatei erstellt haben, die ein Klassenspeicherlayout verwendet, zeigt clang das Speicherlayout an.

$ clang -cc1 -fdump-record-layouts layout.cpp

Layout der Klasse:

*** Dumping AST Record Layout
   0 | class Class
   0 |   class SBase1 (primary base)
   0 |     (SBase1 vtable pointer)
   8 |     int k
  16 |   class SBase2 (base)
  16 |     (SBase2 vtable pointer)
  24 |     int k
  28 |   class SBase3 (base)
  28 |     int k
  32 |   int i
  36 |   char c
  40 |   float f
  48 |   double d
  56 |   short s
  64 |   class VBase (virtual base)
  64 |     (VBase vtable pointer)
  72 |     int j
     | [sizeof=80, dsize=76, align=8
     |  nvsize=58, nvalign=8]

Weitere Informationen zum Speicherlayout

Weitere Informationen zu diesem Clang finden Sie unter Die Immobilien finden Sie bei Eli Bendersky Gefunden im Blog:

http://eli.thegreenplace.net/2012/12/17/dumping-a-c-objects-memory-layout-with-clang/

gcc bietet ein ähnliches Tool „-fdump-class-hierarchy“. Für die oben angegebene Klasse gibt sie (unter anderem) Folgendes aus:

Class Class
   size=80 align=8
   base size=58 base align=8
Class (0x0x141f81280) 0
    vptridx=0u vptr=((&amp; Class::_ZTV5Class) + 24u)
  SBase1 (0x0x141f78840) 0
      primary-for Class (0x0x141f81280)
  SBase2 (0x0x141f788a0) 16
      vptr=((&amp; Class::_ZTV5Class) + 56u)
  SBase3 (0x0x141f78900) 28
  VBase (0x0x141f78960) 64 virtual
      vptridx=8u vbaseoffset=-24 vptr=((&amp; Class::_ZTV5Class) + 88u)

Die Mitgliedsvariablen werden nicht aufgelistet (oder zumindest weiß ich nicht, wie ich sie bekomme), aber Sie können es sehen dass sie zwischen Offset 28 und 64 liegen müssen, genau wie im Clang-Layout.

Sie können sehen, dass eine Basisklasse als primär gekennzeichnet ist. Dadurch entfällt die Notwendigkeit dieser Zeigeranpassung, wenn auf die Klasse als SBase1 zugegriffen wird.

Andere Compiler-Anweisungen

Die folgenden äquivalenten Anweisungen gelten für verschiedene Compiler:

  • gcc: $ g -fdump-class- hierarchy - c layout.cpp
  • Visual C: cl main.cpp /c /d1reportSingleClassLayoutTest_A

Siehe: https://blogs.msdn.microsoft.com/vcblog/2007/05/17/diagnosing-hidden-odr-violations-in-visual-c-and-fixing -lnk2022/

Das obige ist der detaillierte Inhalt vonWie ordnet C Objekte im Speicher an und was bedeutet das für die dynamische Umwandlung und Neuinterpretation?. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Stellungnahme:
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn