2

이 웹 사이트와 프로그래밍 세상이 새롭게 변경되었습니다. 그래서, 나와 함께 인내심을주십시오 :포인터를 얕은 복사 할 때 기본 할당 연산자가 메모리 누수를 생성합니까?

나는 3 개의 규칙에 대해 읽었으며 복사 생성자와 할당 연산자가 어떻게 작동 하는지를 이해했습니다. C++에서 제공하는 기본 객체는 객체의 얕은 복사본 (또는 멤버 고유)을 제공한다는 것을 이해했습니다.

제 질문은 ... 클래스에 동적 할당 메모리를 가리키는 구성원 포인터가 있으면 기본 할당 연산자는 원래 개체에서 포인터로 유지 된 주소 만 개체의 포인터로 복사합니다 에 할당됩니다. 그러나 이것이 메모리 누출을 일으키지 않을까요? 예를 들어 상기 followind 코드 : GC1이 생성 될 때

class GCharacter //Game Character 
     { 
      private: 
       std::string name; 
       int capacity; //the capacity of our tool array 
       int used;  //the nr of elements that we've actually used in that tool array 
       std::string* toolHolder; //string pointer that will be able to reference our ToolArray; 

      public: 
       static const int DEFAULT_CAPACITY = 5; 
      //Constructor 
       GCharacter(std::string n = "John", int cap = DEFAULT_CAPACITY) 
       :name(n), capacity(cap), used(0), toolHolder(new string[cap]) 
       { 
       } 
     } 

    int main() 
    {   GCharacter gc1("BoB", 5); 
       GCharacter gc2("Terry", 5); 
       gc2 = gc1; 
       GCharacter gc3 = gc1; 

       return 0; 
    } 

그래서, 코드, gc1.toolHolder 5 문자열의 일부 동적 할당 된 메모리의 어드레스를 유지한다. 이 후 gc2가 생성되고 동적으로 5 개의 문자열에 메모리를 할당하고 gc2.toolHolder가 주소 135를 보유한다고 가정 해 봅시다.

다음 코드 행은 기본 할당 연산자를 호출하고 gc1의 모든 구성원에서 gc2로의 얕은 복사 이것은 포인터 gc2.toolHolder가 주소 125를 보유하고 있으며 주소 135의 메모리에 더 이상 액세스 할 수 없음을 의미합니다. 따라서 이러한 상황에서 기본 할당 연산자는 메모리 누수를 생성합니까? ... 또는 나는 무엇인가 잘못 이해했다 ??

또 다른 질문은 기본 복사 생성자의 경우 이미 존재하지 않는 객체에서만 호출되기 때문에 gc3.toolHolder가 새 메모리를 할당 할 기회를 얻지 못한다는 것을 의미합니다. 145 번 주소에요? 그러면 gc1.toolHolder에 저장된 주소가 수신됩니까?

좀 더 구체적으로 ... 위와 같은 경우 gc3.toolHolder와 gc1.toolHolder 두 포인터가 있다는 것을 제외하면 gc3없이 같은 주소 125를 참조해야합니다. toolHolder 동적 5 문자열의 새 메모리를 할당합니다.

간단히 말해 동적 할당 메모리를 가리키는 포인터 멤버 변수가있는 클래스를 인스턴스화하면 기본 할당 연산자가 메모리 누수가 발생합니까? 그리고 기본 복사 생성자는 동일한 할당 메모리에 포인터를 공유합니까?

감사합니다.

+1

간단히 말해 RAII 컨테이너를 사용하면 이러한 문제가 발생하지 않습니다. p – chris

+0

예, 메모리 누수가 발생합니다. 좋은 답변은 Daniel에 의해 이미 주어 졌으므로, 여기서'valgrind' 프로그램을 사용하여 메모리 누수 및 유사한 문제를 확인하도록 제안하고자합니다. –

답변

2

메모리가 당신이 생성자에 new로 할당 된 메모리를 해제 소멸자의 부족이다 누출, 다음이 필요합니다 당신이 추가하면

~GCharacter() { delete[] toolHolder; } 

, 당신은 두 번째 문제를 볼 당신 가지고있는 : 기본 생성 된 복사 - ctor 및 할당 그냥 복사/포인터를 할당, 따라서 사본을 가지고 원본과 복사본이 범위를 벗어나면 그들은 모두 메모리를 삭제하려고합니다. 이 double-free는 물론 보다 큰 문제이 메모리 누수보다 많습니다. 메모리가 손상 될 가능성이 높기 때문입니다.

그렇다면 자신 만의 copy-ctor 및 할당 연산자를 추가하고 올바르게 구현하려고합니다. 이 경우 사본의 toolHolder에 대한 메모리를 할당한다는 의미입니다. 일반적으로 어떤 클래스 집합을 구현할 것인지에 대해서는 Rule of Five을 참조하십시오.

+0

나는 이것에 대해 걱정할 필요가 없도록하는 방법에 관한 [Rule of Zero] (http://flamingdangerzone.com/cxx11/2012/08/15/rule-of-zero.html)에 관한 글을 읽을 것을 제안한다;) –

+0

좋아, 알았어. 하지만 내 자신의 소멸자를 제공하더라도 ... 똑같은 질문이 내 머리 속에있다. 'gc2 = gc1'은'gc2.toolHolder'가 더 이상 할당 한 메모리를 참조 할 수 없게 만듭니다. 그게 메모리 누출 아닌가요? BTW, 나는 우리 자신의 copy-ctor와 destructor를 제공하고 동적 메모리를 다룰 때 op를 할당하는 것이 더 낫다는 것을 알고있다.하지만 기본 동작이 어떻게 작동하는지 이해하려고 노력 중이다. – xPlay

+0

@xPlay 물론 올바른 할당 연산자가 필요합니다. 그러나 올바른 복사 - ctor 및 스왑을 재사용하여 버그가 발생할 가능성을 줄이고 복잡성을 줄일 수 있습니다. [here] (http://stackoverflow.com/questions/4421706)를 참조하십시오. –