>백엔드 개발 >C++ >C는 메모리에서 객체를 어떻게 배열하며, 동적 캐스팅 및 재해석은 무엇을 의미합니까?

C는 메모리에서 객체를 어떻게 배열하며, 동적 캐스팅 및 재해석은 무엇을 의미합니까?

DDD
DDD원래의
2024-11-02 03:52:30360검색

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

C 객체의 메모리 레이아웃

질문:

C는 메모리에서 어떻게 배열되나요? 물체? 동적 캐스트는 오프셋을 사용하여 메모리에 있는 개체의 포인터만 조정하는 반면 재해석을 사용하면 이 포인터에 대해 모든 작업을 수행할 수 있다고 들었습니다. 나는 잘 이해하지 못한다. 세부정보를 제공해 주세요!

정답:

메모리 레이아웃

메모리 레이아웃은 주로 구현에 따라 다릅니다. 한 가지 중요한 예외가 있는데, 동일한 액세스 지정자를 가진 멤버 변수가 선언 순서대로 정렬된다는 것입니다.

§ 9.2.14

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

기타 메모리 관리

클래스나 구조체는 멤버 변수 외에도 멤버 변수, 기본 클래스의 하위 객체, 가상 객체도 관리해야 합니다. 함수(예: 가상 테이블) 및 이 데이터의 패딩 및 정렬을 위해 제공되는 공간입니다. 구현에 따라 다르지만 Itanium ABI 사양이 널리 선택됩니다. gcc와 clang이 이를 따릅니다(적어도 어느 정도).

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

Itanium ABI

물론 Itanium ABI는 C 표준의 일부가 아니며 구속력도 없습니다. 자세한 내용은 구현자의 문서와 도구를 참조해야 합니다. clang은 클래스의 메모리 레이아웃을 볼 수 있는 도구를 제공합니다. 예를 들어 다음과 같습니다.

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

클래스 메모리 레이아웃을 사용하는 소스 파일을 생성한 후 clang은 메모리 레이아웃을 표시합니다.

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

클래스 레이아웃:

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

더 많은 메모리 레이아웃 정보

이 clang에 대한 추가 정보 이 기능은 Eli Bendersky의 블로그에서 찾을 수 있습니다:

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

gcc는 유사한 도구 `-fdump-class-hierarchy'를 제공합니다. 위에 제공된 클래스의 경우 다음을 출력합니다(무엇보다도):

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)

멤버 변수를 항목화하지 않습니다(또는 적어도 변수를 얻는 방법을 모릅니다). 그러나 다음을 볼 수 있습니다. clang 레이아웃과 마찬가지로 오프셋 28과 64 사이에 위치해야 합니다.

기본 클래스가 Primary로 지정되어 있는 것을 확인할 수 있습니다. 이렇게 하면 클래스가 SBase1로 액세스될 때 이러한 포인터 조정이 필요하지 않습니다.

기타 컴파일러 지시어

다음과 동등한 지시어가 다른 컴파일러에 적용됩니다.

  • gcc: $ g -fdump-class- Hierarchy - c 레이아웃.cpp
  • 비주얼 C: cl main.cpp /c /d1reportSingleClassLayoutTest_A

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

위 내용은 C는 메모리에서 객체를 어떻게 배열하며, 동적 캐스팅 및 재해석은 무엇을 의미합니까?의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

성명:
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.