c++ ) operator함수에서 오브젝트를 리턴할 때 자동으로 삭제되어 리턴이 되지 않는 문제

조회수 1773회

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되어서 정상적으로 리턴이 되지 않습니다.

원인이 무엇일까요?

https://kldp.org/node/132271

저와 비슷한 경우인 것 같아 살펴보았지만 저는 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

답변을 하려면 로그인이 필요합니다.

프로그래머스 커뮤니티는 개발자들을 위한 Q&A 서비스입니다. 로그인해야 답변을 작성하실 수 있습니다.

(ಠ_ಠ)
(ಠ‿ಠ)