336x280(권장), 300x250(권장), 250x250, 200x200 크기의 광고 코드만 넣을 수 있습니다.

아래 코드와 같이 객체 간 (디폴트 대입연산자를 통한) 대입연산을 시행하는 경우, 

소멸자의 호출과정에서 문제가 발생한다. 즉, 두 개의 객체를 생성했지만 소멸자는 한번 밖에 호출되지 않는다.


이는 디폴트 대입연산자를 통한 대입연산은 얕은 복사를 수행하기 때문에 생기는 문제다.

얕은 복사(Shallow Copy)는 객체의 멤버변수를 단순 복사해서 다른 객체의 멤버 변수에 옮기는 역할만을 수행한다.


문자열과 같은 포인터 변수를 복사하는 경우, 포인터 변수가 참조하는 주소값을 복사하게 되고 

따라서 얕은 복사가 수행된 후 두 객체는 하나의 같은 문자열 데이터를 참조하게 된다.


한 객체가 소멸자를 호출하여 소멸하면 그 객체가 가지고 있던 문자열 데이터 또한 소멸하게 된다.

이후 다른 객체가 소멸자를 호출할 때, 그 객체의 포인터 변수가 가리키는 문자열 데이터는 이미 소멸한 상태이므로

이미 지워진 문자열을 중복 소멸하는 문제가 발생하게 된다.


아래 코드를 컴파일하면 정상적으로 수행되긴 하지만 종료 과정에서 에러가 발생한다.





에러가 발생한 지점이 debug_heap.cpp의 _CtrIsValidHeapPointer(block)에서 발생한 것으로 보아 

현재로선 정확한 현상 진단을 하기는 어렵지만 정상적으로 메모리 해제가 이루어지지 않음으로써 발생하는 문제로 추정한다.


이는 얕은 복사를 수행하는 디폴트 대입연산자 대신 깊은 복사(Deep Copy)를 수행하는 직접 대입 연산자를 정의하면 해결된다. (주석 부분)


#define _CRT_SECURE_NO_WARNINGS


#include <iostream>

#include <cstring>


using namespace std;


class Person

{

private:

char *name;

int age;

public:

Person(char *myname, int myage)

{

int len = strlen(myname) + 1;

name = new char[len];

strcpy(name, myname);

age = myage;

}

void ShowPersonInfo() const

{

cout << "이름: " << name << endl;

cout << "나이: " << age << endl;

}

~Person()

{

delete[]name;

cout << "called destructor!" << endl;

getchar();

}

// Person& operator=(const Person& ref)

// {

//  delete[]name;

//  int len = strlen(ref.name) + 1;

//  name = new char[len];

//  strcpy(name, ref.name);

//  age = ref.age;

//  return *this;

// } 

};


int main(void)

{

Person man1("Lee Dong woo", 29);

Person man2("Yoon ji yul", 22);

man2 = man1;


man1.ShowPersonInfo();

man2.ShowPersonInfo();


return 0;

}



'language > C|C++' 카테고리의 다른 글

데이터 상수화, 포인터 상수화  (0) 2016.07.21
SwitchViewDemo  (0) 2016.06.06
#pragma  (0) 2016.05.02
인라인(Inline) 함수  (0) 2016.05.02
#ifdef, #endif,.. Preprocessor  (0) 2016.05.01
블로그 이미지

saylin

,