어셈블리 언어 측면에서 OOP“개체”와“클래스”는 메모리에서 어떻게 구성됩니까?


13

객체는 메모리에서 어떻게 구성됩니까?

예를 들어, 함수는 메모리의 코드 조각이며 스택 및 / 또는 레지스터를 통해 매개 변수를 기대하고 자체 스택 프레임을 처리한다는 것을 알고 있습니다.

그러나 객체는 훨씬 더 복잡한 구조입니다. 그들은 어떻게 구성되어 있습니까? 각 객체에는 메소드에 대한 "링크"가 있고 해당 메소드에 주소를 전달합니까?

이 주제에 대한 좋은 설명을 보는 것이 좋습니다.

UPD. 나는 질문을보다 정확하게 만들었고 주로 정적으로 언어를 입력하는 데 관심이 있습니다.


4
다른 언어, 특히 동적 형식 언어와 정적 형식 언어 사이에서 크게 다를 수 있습니다. 질문을 가장 관심있는 OO 언어로 좁힐 수 있습니까?
Bart van Ingen Schenau

질문을 업데이트 했으므로 동적으로 입력 된 언어를 이해하기가 더 어렵다고 생각합니다.
Nikolai Golub

답변:


17

동적 디스패치 (다형성)가 없으면 "메소드"는 단순한 함수일 뿐이며 암시적인 추가 매개 변수가있을 수 있습니다. 따라서, 다형성 거동이없는 클래스의 인스턴스는 본질적 struct으로 코드 생성을위한 C 이다.

정적 유형 시스템의 클래식 동적 디스패치에는 기본적으로 하나의 주요 전략 인 vtables가 있습니다. 모든 인스턴스는 유형, 가장 중요한 vtable을 나타내는 (한정된 표현) 추가 포인터 하나 를 얻습니다 . 메소드 당 하나의 함수 포인터 배열. 모든 유형에 대한 전체 메소드 세트 (상속 체인에서)는 컴파일 타임에 알려져 있으므로, 메소드에 연속 인덱스 (N 메소드의 경우 0..N)를 지정하고 함수 포인터를 찾아 메소드를 호출 할 수 있습니다. 이 인덱스를 사용하는 vtable (인스턴스 참조를 추가 매개 변수로 전달 함)

보다 동적 인 클래스 기반 언어의 경우 일반적으로 클래스 자체는 일류 객체이며 각 객체는 대신 해당 클래스 객체에 대한 참조를 갖습니다. 클래스 객체는 언어에 의존하는 방식으로 메소드를 소유합니다 (루비에서 메소드는 객체 모델의 핵심 부분입니다. 파이썬에서는 작은 래퍼가있는 함수 객체 일뿐입니다). 클래스는 일반적으로 수퍼 클래스에 대한 참조도 저장하고, 메소드를 추가하고 변경하는 메타 프로그래밍을 돕기 위해 상속 된 메소드 검색을 해당 클래스에 위임합니다.

클래스를 기반으로하지 않는 다른 많은 시스템이 있지만 크게 다르므로 흥미로운 디자인 대안 중 하나만 선택합니다. 프로그램의 어느 곳에서나 모든 유형에 새로운 (세트) 메소드를 추가 할 수있는 경우 ( 예를 들어 Haskell의 유형 클래스와 Rust의 특성), 컴파일하는 동안 전체 메소드 세트를 알 수 없습니다. 이를 해결하기 위해 특성 당 vtable을 생성 하고 특성 구현이 필요할 때 전달합니다. 즉, 다음과 같은 코드입니다.

void needs_a_trait(SomeTrait &x) { x.method2(1); }
ConcreteType x = ...;
needs_a_trait(x);

이 컴파일됩니다 :

functionpointer SomeTrait_ConcreteType_vtable[] = { &method1, &method2, ... };
void needs_a_trait(void *x, functionpointer vtable[]) { vtable[1](x, 1); }
ConcreteType x = ...;
needs_a_trait(x, SomeTrait_ConcreteType_vtable);

이것은 vtable 정보가 객체에 포함되지 않았 음을 의미합니다. 예를 들어, 다양한 유형을 포함하는 데이터 구조에 저장 될 때 올바르게 작동하는 "특성 인스턴스"에 대한 참조를 원하면 팻 포인터를 작성할 수 있습니다 (instance_pointer, trait_vtable). 이것은 실제로 위 전략의 일반화입니다.


5

이것은 당신의 질문이 매우 광범위하므로 속담의 의미에 대한 대답입니다.

1. 공개 정보원 연구

"어셈블리 객체 지향 프로그래밍"을위한 Google은 다양한 관련 리소스를 나열합니다.

조립, 에단 J. 엘 드리지 년 12 월 15 일에서 객체 지향 프로그래밍, 2011 년 3 링크 외모 좋은으로왔다

2. 기존의 손으로 쓴 코드에서 학습

OOP를 명시 적으로 선언하여 널리 사용되는 어셈블리 언어로 작성된 소스 코드를 연구하여 작동 방식을 확인할 수 있습니다.

3. 컴파일러가 생성 한 코드 패턴을 통해 학습

선택한 OOP 컴파일러가 생성 한 중간 어셈블리 언어 파일을 연구하여 작동 방식을 확인할 수 있습니다. C ++ 및 FreePascal 컴파일러를 모두 구성하여 고급 OOP 코드가 어셈블리 언어 코드로 변환 된 내용을 확인할 수 있습니다.

4. 상식으로 퍼즐을 해결

다른 답변의 힌트를 이미 알고 있으므로 너무 늦습니다. 그러나 인터넷을 검색하기가 쉬워지고 어려운 방법을 배운 자원 봉사자로부터 몇 시간 동안 아무런 노력없이 답변을 얻을 수있는 사이트가 있기 전에는 누구나 무료로 사용할 수있는 유일한 작업 방법이었습니다

"어떻게 구현 할까?"

며칠 동안 백그라운드 사고 프로세스를 실행 한 후 몇 가지 초안 디자인을 버린 후에는 다른 프로그래머가 구현하고 이미 구현 한 솔루션과 매우 유사하다는 것을 알 수 있습니다.


이제 내 대답은 의견 기반이며 OP의 질문에 직접 대답하지 않으며 고위 고위 사용자는 자유롭게 저에게 투표 할 수 있습니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.