OZ1NG의 뽀나블(Pwnable)

[C++] 클래스 생성자의 첫 번째 인자 본문

Tips

[C++] 클래스 생성자의 첫 번째 인자

OZ1NG 2022. 7. 19. 18:18

[*] 클래스 생성자의 첫 번째 인자에는 항상 해당 클래스를 저장할 공간의 주소가 들어간다.

// cpp new test
#include <iostream>

using namespace std;

class PageHeap{
public:
    int a = 1;
    int b = 2;

    PageHeap(){
        cout << "PageHeap!" << endl;
        a = 3;
    }

    PageHeap(int A){
        cout << "PageHeap!" << endl;
        a = A;
    }
};

union PageHeapStorage {
    char memory[sizeof(PageHeap)];
    uintptr_t extra;
};
static PageHeapStorage pageheap_;

int main(){

    new (&pageheap_.memory) PageHeap; // [A]
    new PageHeap(5); // [B]

    return 0;
}
   0x0000000000401207 <+17>:    lea    rbx,[rip+0x2f92]        # 0x4041a0 <pageheap_>
   0x000000000040120e <+24>:    mov    rsi,rbx
   0x0000000000401211 <+27>:    mov    edi,0x8
   0x0000000000401216 <+32>:    call   0x4012f4 <operator new(unsigned long, void*)> // [A-1]
   0x000000000040121b <+37>:    mov    r12,rax
   0x000000000040121e <+40>:    mov    rdi,r12
   0x0000000000401221 <+43>:    call   0x40131e <PageHeap::PageHeap()> // [A-2]
   0x0000000000401226 <+48>:    mov    edi,0x8
   0x000000000040122b <+53>:    call   0x4010c0 <operator new(unsigned long)@plt> // [B-1]
   0x0000000000401230 <+58>:    mov    r12,rax
   0x0000000000401233 <+61>:    mov    esi,0x5
   0x0000000000401238 <+66>:    mov    rdi,r12
   0x000000000040123b <+69>:    call   0x401378 <PageHeap::PageHeap(int)> // [B-2]

- [A] : 인자가 없는 생성자의 경우

  - A-1 : new로 정적할당된 공간(pageheap_)에 클래스를 저장할 준비를 한다.

  - A-2 : 생성자의 첫 번째 인자로 new의 리턴값(= pageheap_의 주소)를 넣고 생성자를 호출한다.

- [B] : 인자가 있는 생성자의 경우

  - B-1 : new로 클래스를 저장할 공간을 동적할당한다.

  - B-2 : 첫 번째 인자로 new의 리턴값(동적할당된 공간)을 넣고 두 번째 인자에 생성자의 첫번째 인자를 넣은 뒤 생성자를 호출한다.

 

[*] 종합

1. C++에서 클래스의 생성자는 항상 첫번째 인자로 클래스를 저장할 공간의 주소를 받는다.

Comments