동적 배열을 멤버로 들고 있는 클래스를 만들었는데, 이 객체를 복사해서 쓰다 보면 프로그램 끝날 때 크래시가 납니다. valgrind로는 double free 비슷한 게 잡히고요. 대충 이런 구조예요.


class Buffer {
  int* data;
public:
  Buffer(int n) { data = new int[n]; }
  ~Buffer() { delete[] data; }
};
Buffer a(10);
Buffer b = a;  // 얕은 복사


복사 생성자를 따로 안 만들었더니 컴파일러 기본 복사가 포인터 값만 그대로 베껴서, a랑 b가 같은 메모리를 가리키다가 둘 다 소멸될 때 같은 주소를 두 번 delete 하는 것 같아요. 이거 소멸자만 있으면 안 되고 복사 생성자, 복사 대입 연산자까지 다 만들어서 깊은 복사를 해줘야 하는 거죠? 흔히 말하는 그 규칙 이름이랑 정확히 뭘 정의해야 하는지 알려주시면 감사하겠습니다.