c++ ) operator함수에서 오브젝트를 리턴할 때 자동으로 삭제되어 리턴이 되지 않는 문제
조회수 1799회
linked list를 작성하고 있는데
+=, = operator를 작성하였고 정상적으로 동작하는 것도 확인하였습니다.
그 후 + operator를 작성하는데
unvlist unvlist::operator+(const unvlist &ul){
unvlist *list = new unvlist();
*list = *this;
*list += ul;
return *list;
}
와 같이 작성하니 이유를 모를 메무리 누수(12byte) Detected memory leaks! Dumping objects -> {216} normal block at 0x0122B298, 12 bytes long. Data: < 8 " " > 05 00 00 00 38 B3 22 01 D0 B4 22 01 Object dump complete. 가 일어나는데 아마 *list를 함수안에서 생성 한 후 delete하는 과정이 없어서 그런 것 같아
unvlist unvlist::operator+(const unvlist &ul) {
unvlist list = unvlist();
list = *this;
list += ul;
return list;
}
와같이 작성하였는데
unvlist l = unvlist(), ll=unvlist();
l = *l1;
l += *l2;
ll = *l1 + *l2;
를 실행하면 l같은 경우 정상적으로 작동하나 ll = *l1 + *l2를 실행하는 순간 operator=에서 오류가 납니다
원인은 *l1 + *l2 가 Size는 정상적으로 들어가지만 나머지 노드들이 하나도 들어가지 않습니다.(NULL)
operator+ 함수 내에서 확인해 보니 리턴 전까지는 정상적으로 동작합니다.
아래는 제 destructor함수입니다
unvlist::~unvlist(){
clear();
// free(this);
}
void unvlist::clear(){
NodeBase* T = Tail;
NodeBase* tmp = Head;
NodeBase* ttmp;
while (tmp != NULL){
ttmp = tmp->nextNode;
delete tmp;
tmp = ttmp;
}
Tail = NULL;
Size = 0;
}
unvlist class는 다음과 같습니다
class unvlist {
private:
int Size;
NodeBase* Head;
NodeBase* Tail;
public:
unvlist operator+(const unvlist &ul);
unvlist& operator=(const unvlist &ul);
unvlist& operator+=(const unvlist &ul);
bool operator==(const unvlist &ul);
bool operator!=(const unvlist &ul);
....
}
즉 정리하자면
*l1+*l2의 값이 (operator+에서) return 되기 전에 자동으로 delete되어서 정상적으로 리턴이 되지 않습니다.
원인이 무엇일까요?
저와 비슷한 경우인 것 같아 살펴보았지만 저는 return type을 그냥 type으로 맞게 한 것임에도 오류가 나는 이유를 모르겠어 질문 드립니다.
1 답변
-
C++ 에서 많이 실수 하는 것중에 하나가 복사생성자인데요.
복사생성자는 call by value 형태로 전달할 때, 호출되는 생성자입니다.
즉, 포인터(*)나 레퍼런스(&) 타입이 아닌 함수 인자로 넘기거나, return 으로 넘겨받을 때, 복사생성자가 호출됩니다.
복사생성자의 역할은 인스턴스(객체)를 어떻게 복사할 지 결정하는 데, 기본적으로는 앝은(swallow) 복사를 수행합니다. 하지만 생성자에서 new 혹은 malloc 으로 메모리를 생성하고, 소멸자에서 메모리를 해제하는 경우라면 필히 복사생성자를 만들어 깊은 복사를 수행하도록 해야 합니다.
이 문제가 아닌지 의심됩니다.
주
얕은 복사 데이터멤버에 포인터가 있는 경우, 포인트의 주소만 복사함. 이 경우 원본과 사본이 같은 포인터를 가리키고 있는 데, 둘 중 한 곳에서 포인터의 메모리를 해제하는 경우, 다른 한쪽에서도 포인터가 해제됩니다.
깊은 복사 데이터멤버의 포인터도 모두 복제하여 사본과 원본이 공유하고 있는 데이터가 없게 만듭니다.
- 답변 감사합니다 사실 질문 올린 후 Three Rules? 를 보고 복사생성자를 만들었더니 해결되었습니다 Sang Hoon Han 2016.5.13 19:33
- 친절한 답변 감사합니다! Sang Hoon Han 2016.5.13 19:33
댓글 입력