2010-04-27 10 views
5

다음 버그가 발생했습니다.벡터 관련 메모리 할당 질문

  • 나는 종류가 Foo입니다. 이 클래스의 인스턴스는 std :: vector vecclass B에 저장됩니다.
  • Foo 클래스에서 new을 사용하여 메모리를 할당하고 ~Foo()에서 해당 객체를 삭제하여 클래스 A의 인스턴스를 만듭니다.

코드가 컴파일되지만 런타임에 오류가 발생합니다. Foo의 디스트 리뷰 터에서 delete my_a을 비활성화하면 어떻게됩니까? 코드는 잘 실행되지만 (메모리 누수가 발생할 것입니다).

누군가 여기서 잘못된 점을 설명하고 문제를 제안 할 수 있습니까?

감사합니다.

class A{ 
     public: 
      A(int val); 
      ~A(){}; 
      int val_a; 

}; 

A::A(int val){ 
     val_a = val; 
     }; 

class Foo {  
     public: 
      Foo(); 
      ~Foo(); 
      void createA(); 
      A* my_a; 
}; 

Foo::Foo(){ 
    createA(); 
}; 

void Foo::createA(){ 
    my_a = new A(20); 
}; 

Foo::~Foo(){ 
    delete my_a; 

}; 



class B { 
     public: 
      vector<Foo> vec;    
      void createFoo();    
      B(){}; 
      ~B(){}; 
}; 


void B::createFoo(){ 
    vec.push_back(Foo()); 
}; 


int main(){ 
    B b; 

    int i =0; 
    for (i = 0; i < 5; i ++){ 
     std::cout<<"\n creating Foo"; 
     b.createFoo(); 
     std::cout<<"\n Foo created"; 
     } 
    std::cout<<"\nDone with Foo creation"; 

    std::cout << "\nPress RETURN to continue..."; 
    std::cin.get(); 

    return 0; 
} 

답변

7

Foo에 대한 복사 생성자와 할당 연산자를 구현해야합니다. 소멸자가 필요하다고 생각할 때마다 분명히이 두 가지가 필요합니다. 그들은 많은 장소에서, 특히 개체를 표준 라이브러리 컨테이너에 넣는 데 사용됩니다.

복사 생성자는 다음과 같아야합니다

Foo :: Foo(const Foo & f) : my_a(new A(* f.my_a)) { 
} 

및 할당 연산자 : 더 나은 여전히 ​​

Foo & Foo :: operator=(const Foo & f) { 
    delete my_a; 
    my_a = new A(* f.my_a); 
    return * this; 
} 

또는를 동적으로 푸 클래스의 A 인스턴스를 생성하지 않습니다

class Foo {  
     public: 
      Foo(); 
      ~Foo(); 
      void createA(); 
      A my_a; 
}; 

Foo::Foo() : my_a(20) { 
}; 
+0

감사합니다. 그렇다면 클래스 A의 인스턴스를 어떻게 작성해야합니까? 코드 스 니펫 (snippet)을 많이 주시면 감사하겠습니다. 또한 생성자와 대입 연산자 코드를 어떻게 복사 할 것인가. 대단히 고마워요 – memC

+1

Neil 당신은 오타가 있습니다 ... new A (f.my_a); -> 새로운 A (* f.my_a); – TimW

+0

안녕 Neil, 코드 스 니펫을 주셔서 대단히 감사드립니다. 사실, 벡터에 Foo 인스턴스를 두는 동안 my_a에 int val을 전달하려고합니다. 어떻게해야합니까? -> 나는 다음과 같이하고 싶다 : (물론 작동하지 않는다)'vec.push_back (Foo() : my_a (40)' – memC

2

Foo 객체가 복사되고 모든 복사본이 삭제 될 때 s에서 delete가 호출됩니다. 포인터 값 my_a. Foo에 대한 복사 및 대입 연산자를 구현하거나 스마트 포인터를 사용하십시오.

Foo(const Foo& s) : my_a(s.my_a ? new A(*s.my_a) : 0) { 
} 

Foo& operator= (const Foo& s) { 
    Foo temp(s); 
    temp.swap (*this); 
    return *this; 
} 

void swap (Foo &s) { 
    std::swap (my_a, s.my_a); 
}; 
+0

스마트 포인터 +1 +1 – hamishmcn

+0

Tim 감사합니다. – memC

3

복사 생성자를 지정하지 않으면 컴파일러에서 자동으로 생성자를 지정합니다. 컴파일러에서 생성 한 복사 생성자는 다음과 같습니다.

Foo::Foo(const Foo& copy) 
    : my_a(copy.my_a) 
{} 

Woops! 포인터 만 복사하고 가리키는 메모리는 복사하지 않습니다. 임시 Foo() (createFoo())과 벡터에 복사 된 메모리가 동일한 메모리를 가리키고 있으므로 메모리가 두 번 삭제되어 두 번째 삭제시 프로그램이 충돌합니다.

이 같은 보이는 복사 생성자를 만들어야합니다 copy는 NULL my_a 멤버가있는 경우이 충돌

Foo::Foo(const Foo& copy) 
    : my_a(new A(*copy.my_a)) 
{} 

주를, 또한 당신이 지정하지 않은 A에 복사 생성자를 호출 어느 한 쪽. 따라서 더 많은 변화를 원할 것입니다. 또한 operator= 과부하가 필요합니다.