동적 할당과 클래스에 대한 질문
글쓴이: 익명 사용자 / 작성시간: 일, 2020/05/03 - 8:34오후
class Stack { private: int * _stack; int _size; public: Stack(int array[], int size); ~Stack(); Stack Stack::operator*(int num); //나머지 함수 생략 }; <cpp> 다음과 같은 클래스가 있다 합시다. 그러면 생성자를 만들 때엔, <cpp> _stack = new int[MAX_STACK];
다음과 같이 동적 메모리 선언을 하고,
Stack::~Stack() { delete[] _stack }
과 같이 소멸자에서 동적 메모리를 해제하는 delete[] 연산자를 삽입하는 것이 일반적이겠죠? 근데 저에게 작은 문제가 생겼습니다ㅠㅠ
Stack Stack::operator*(int num) { int new_size = this->_size; int array[MAX_STACK] = { 0 }; for (int i = 0; i < MAX_STACK; i++) { if (i < this->_size) { array[i] = num * this->_stack[i]; } else { array[i] = 0; } } return Stack(array, new_size); }
다음 함수에서 return Stack을 하고 중괄호가 닫힐 때 Stack에 있는 소멸자가 작동해버리고, 그 때 delete[]도 같이 작동해서 _stack에 있는 값들을 참조할 수 없는 문제가 생겨버렸습니다. 실제로 소멸자에 있는 delete[]를 지워버리면 잘 굴러갑니다. 대신 저희 컴퓨터 메모리가 많이 아파할 것 같지만요. 어떻게 코드를 바꾸어야 소멸자 속 delete[]를 유지하면서 프로그램이 정상작동하게 할 수 있을까요?
Forums:
rule of three/five
어떻게 보느냐에 따라 다른데, memory buffer의 ownership 문제죠. local stack에 할당되었던 Stack object가 return과 함께 사라지는데, 사라지기 전에 (개념상) return value object에다 적잘한 카피를 해줘서, 그 사라짐이 문제를 일으키지 않았어야 합니다.
하지만, 실제로는 사라지면서 자기가 쥐고 있던 buffer를 날리는데, 임시 return value object에다가는 그냥 shallow copy를 해줘서, return value object의 _stack은 dangling pointer가 됩니다. 다른 말로 이 _stack이 가리키는 버퍼의 ownership을 넘겨주지 않은 거죠.
이 디자인을 유지할 경우 move semantic이 적용될 수 있게끔 rule of five에 따라 적당한 함수들을 추가해 주시는 게 한 방법이고, 아니면 _stack에 raw pointer 대신 unique_ptr을 사용하는 쪽도 고려할 수 있습니다.
https://stackoverflow.com/questions/16711697/is-there-any-use-for-unique-ptr-with-array/16804634
https://kldp.org/node/163145
https://kldp.org/node/163145
이 분과 비슷한 종류의 실수를 저지르고 계신 듯.
C++ 객체로 자원 관리를 하려면 생성자+소멸자+복사 생성자+복사 할당 연산자(C++11부터는 +이동 생성자+이동 할당 연산자)를 모두 숙지하고 있어야 합니다.
댓글 달기