포스트

[C++ Error] Double Free 에러 해결하기

Double Free 에러 해결하기

문제 발생

MyString 클래스의 객체를 복사하는 과정에서 발생한 double free 오류입니다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
// MyString.cpp
class MyString {
public:
    MyString(const char* init) {
        size_ = strlen(init);
        str_ = new char[size_ + 1];
        strcpy(str_, init);
    }
    MyString(const MyString& copy) {
        str_ = copy.str_;  // 문제의 원인: 얕은 복사
        size_ = copy.size_;
    }
    ~MyString() {
        delete[] str_;  // 여기에서 double free 발생
    }

private:
    char* str_;
    int size_;
};

// main.cpp
int main() {
    MyString str1("Hello World!");
    MyString str2 = str1;  // 복사 생성자 사용
    return 0;  // 두 객체의 소멸 시 double free 발생
}

오류 메시지:

1
2
main(57049,0x1fad68c00) malloc: Double free of object 0x14ba040b0
main(57049,0x1fad68c00) malloc: *** set a breakpoint in malloc_error_break to debug

문제 분석

오류 메세지에서의 힌트

메모리 주소 0x14ba040b0에서 객체의 메모리가 두 번 해제되었습니다. str1str2는 동일한 메모리 주소를 가리키는 str_를 공유하므로, 한 객체의 소멸자가 메모리를 해제한 후 또 다른 객체의 소멸자가 동일한 메모리 주소를 해제하려고 시도했습니다.

왜 같은 객체가 2번 해제되는가?

MyString의 복사 생성자가 멤버 변수 str_에 대해 깊은 복사(deep copy)를 수행하지 않고 얕은 복사(shallow copy)를 수행했기 때문입니다. 이로 인해 두 객체가 메모리 주소를 공유하며, 한 객체가 소멸하면서 할당된 메모리를 해제하고, 다른 객체가 다시 같은 메모리를 해제하려고 하여 double free 오류가 발생합니다.

왜 2번 해제되면 안 되는가?

메모리가 한 번 해제되면, 해당 메모리 주소는 시스템에 의해 재사용 준비가 됩니다. 이미 해제된 메모리 주소를 다시 해제하려고 하면 메모리 관리 시스템이 손상될 수 있으며, 이는 프로그램의 충돌이나 예측 불가능한 다른 행동을 초래할 수 있습니다. 또한, 보안 측면에서도 큰 위험을 수반합니다.

문제 해결

이 문제를 해결하기 위해 복사 생성자를 수정하여 각 객체가 자신의 메모리를 독립적으로 가질 수 있도록 깊은 복사를 구현합니다.

1
2
3
4
5
MyString(const MyString& copy) {
    size_ = copy.size_;
    str_ = new char[size_ + 1];
    strcpy(str_, copy.str_);  // 깊은 복사 수행
}

이 수정으로 각 MyString 객체는 별도의 메모리 영역을 가지게 되어 소멸 시점에 발생하는 문제를 방지할 수 있습니다.

결론

Double Free는 메모리 관리에 있어서 심각한 오류로, 적절한 복사 생성자의 구현이 필수적입니다. 프로그램의 안정성을 확보하고 보안 문제를 예방하기 위해 깊은 복사를 통한 메모리 관리가 중요합니다.

이 기사는 저작권자의 CC BY 4.0 라이센스를 따릅니다.

인기 태그