Maison  >  Article  >  développement back-end  >  Comment C organise-t-il les objets en mémoire, et qu'est-ce que cela signifie pour la diffusion et la réinterprétation dynamiques ?

Comment C organise-t-il les objets en mémoire, et qu'est-ce que cela signifie pour la diffusion et la réinterprétation dynamiques ?

DDD
DDDoriginal
2024-11-02 03:52:30307parcourir

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

Disposition de la mémoire des objets C

Question :

Comment le C est-il disposé en mémoire ? Objet? J'ai entendu dire que le casting dynamique ajuste uniquement le pointeur de l'objet en mémoire, avec décalage tandis que la réinterprétation permet de faire n'importe quelle opération sur ce pointeur ; Je ne comprends pas très bien. Veuillez fournir des détails !

Réponse :

Disposition de la mémoire

La disposition de la mémoire dépend principalement de l'implémentation. Il existe une exception clé, à savoir que les variables membres avec le même spécificateur d'accès seront classées dans l'ordre de déclaration.

§ 9.2.14

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

Autre gestion de la mémoire

En plus des variables membres, une classe ou une structure doit également gérer les variables membres, les sous-objets de la classe de base, les variables virtuelles fonctions (telles qu'une table virtuelle) et l'espace prévu pour le remplissage et l'alignement de ces données. Cela dépend de l'implémentation, mais la spécification Itanium ABI est un choix populaire. gcc et clang le suivent (au moins dans une certaine mesure).

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

Itanium ABI

Bien entendu, l'Itanium ABI ne fait pas partie du standard C et n'est pas contraignant. Pour des informations plus détaillées, vous devrez consulter la documentation et les outils de l'implémenteur. clang fournit un outil pour afficher la disposition de la mémoire d'une classe. Par exemple, ce qui suit :

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);
}

Après avoir créé un fichier source qui utilise une disposition de mémoire de classe, clang affichera la disposition de mémoire.

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

Disposition de la classe :

*** 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]

Plus d'informations sur la disposition de la mémoire

En savoir plus sur ce clang Informations sur la fonctionnalité peut être trouvée sur le blog d'Eli Bendersky :

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

gcc fournit un outil similaire `-fdump-class-hierarchy'. Pour la classe donnée ci-dessus, il affiche (entre autres) :

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)

Il ne détaille pas les variables membres (ou du moins je ne sais pas comment les obtenir), mais vous pouvez voir qu'ils doivent être situés entre le décalage 28 et 64, tout comme dans la disposition Clang.

Vous pouvez voir qu'une classe de base est désignée comme primaire. Cela élimine le besoin d'ajuster le pointeur lorsque l'on accède à la classe en tant que SBase1.

Autres directives du compilateur

Les directives équivalentes suivantes s'appliquent aux différents compilateurs :

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

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

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Déclaration:
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn