2011-01-22 1 views
0

편집 : 삭제 연산자를 추가해도 Valgrind 출력이 변경되지 않는 이유를 설명 할 수 있습니까? 제게 C++ 서적을 읽어달라고 부탁하지 마십시오. 저는 한 쌍을 살펴보고 대답을 찾지 못했습니다.C++의 메모리 누수가 삭제 명령문을 추가 한 후에 악화되는 것 같습니다

저는 C++을 처음 접했습니다. 자바 세계에서 왔기 때문에 새로운 연산자와 삭제 연산자를 사용하는 방법을 이해하는 데 어려움이 있습니다.

클래스 (MyClass)를 시작하는 메소드 (myMethod())가 있습니다. MyClass에는 new 및 new [] 연산자를 사용하여 몇 개의 배열과 몇 개의 다른 객체가 생성됩니다. 처음에는이 클래스에 대해 작성된 소멸자가 없었습니다. 컨트롤이 내 메서드에서 main으로 반환되면 MyClass 개체와 관련된 모든 것이 자동으로 "해제"됩니다.

내가 Valgrind의 내 프로그램을 실행

, 이것은 내가 가진 누출 요약은 다음과 같습니다

==9446== LEAK SUMMARY: 
==9446== definitely lost: 1,957,019 bytes in 38 blocks. 
==9446== indirectly lost: 4,171,184 bytes in 3,040 blocks. 
==9446==  possibly lost: 0 bytes in 0 blocks. 
==9446== still reachable: 91,984 bytes in 991 blocks. 
==9446==   suppressed: 0 bytes in 0 blocks. 
==9446== Reachable blocks (those to which a pointer was found) are not shown. 
==9446== To see them, rerun with: --show-reachable=yes 

그래서 나는 모든 배열을 삭제하고 null로 개체를 설정하는 소멸자를 추가했다. 명시 적으로 MyClass 객체에서 delete를 호출하지 않습니다. 이제 Valgrind를 사용하여 프로그램을 실행하면 이것이 누수 요약입니다.

LEAK SUMMARY: 
==9223== definitely lost: 1,957,019 bytes in 38 blocks. 
==9223== indirectly lost: 4,171,184 bytes in 3,040 blocks. 
==9223==  possibly lost: 0 bytes in 0 blocks. 
==9223== still reachable: 91,984 bytes in 991 blocks. 
==9223==   suppressed: 0 bytes in 0 blocks. 
==9223== Reachable blocks (those to which a pointer was found) are not shown. 
==9223== To see them, rerun with: --show-reachable=yes 

명시 적으로 MyClass 개체를 삭제하면 손실 된 바이트의 수가 더 많습니다.

==9268== LEAK SUMMARY: 
==9268== definitely lost: 3,353,187 bytes in 1,253 blocks. 
==9268== indirectly lost: 28,376 bytes in 343 blocks. 
==9268==  possibly lost: 0 bytes in 0 blocks. 
==9268== still reachable: 91,984 bytes in 991 blocks. 
==9268==   suppressed: 0 bytes in 0 blocks. 
==9268== Reachable blocks (those to which a pointer was found) are not shown. 
==9268== To see them, rerun with: --show-reachable=yes 

난 MyMethod라는 (exitting에서 이전 메소드 freeMemory에서() 및 다음 호출 freeMemory에서()에 소멸자의 이름을 변경하려)이 누설 요약이다. 이것은 둘 중 하나보다 높습니다.

== LEAK SUMMARY: 
==8998== definitely lost: 5,271,299 bytes in 1,205 blocks. 
==8998== indirectly lost: 67,264 bytes in 410 blocks. 
==8998==  possibly lost: 0 bytes in 0 blocks. 
==8998== still reachable: 91,984 bytes in 991 blocks. 
==8998==   suppressed: 0 bytes in 0 blocks. 
==8998== Reachable blocks (those to which a pointer was found) are not shown. 
==8998== To see them, rerun with: --show-reachable=yes 

제 질문은 무슨 일입니까? Valgrind는 MyClass의 생성자와 MyClass의 메서드에서 누수가 있음을 나타냅니다. 누군가가 새 연산자와 삭제 연산자가 어떻게 작동하는지 설명 할 수 있습니까? 나는 명확한 자원을 온라인으로 찾을 수 없으므로, 누군가가 저를 그러한 자원으로 안내 할 수 있다면 그것은 또한 위대 할 것입니다!

+1

좋은 초보자 C++ 서적에 앉아 있어야하는 것처럼 들립니다. 왜냐하면 여기에 기초가 분명하지 않기 때문입니다. – Falmarri

+0

42 번 라인의 타월 작업자를 잊어 버렸습니다. –

+1

관련 코드를 게시하십시오. –

답변

6

Java에서 왔으므로 가장 먼저 C++에서 new을 사용할 필요가 없음을 먼저 언급해야합니다.

T 유형의 변수가 필요한 경우 T 유형의 변수 만 선언하십시오. 그게 전부 야. 해당 어레이

대신 포인터와 new를 사용하는

#include <vector> 

int main() 
{ 
    std::vector<int> v(10); // 10 elements 
    v.resize(42);    // now 42 elements 
} 

그것은 자동으로 메모리를 제대로 관리처럼 std::vector 사용합니다.

발생한 오류에 대해서는 일 가능성이 높습니다.은 개체를 복사 할 수있는 모든 방법을 고려하지 않았기 때문에 발생합니다. (C++ 98 용) 규칙은 사용자 지정 소멸자, 사용자 지정 복사본 생성자 또는 사용자 지정 복사본 할당 연산자가 필요한 경우 세 가지가 모두 필요할 것이라고 말합니다. 그러나 다시 말하자면, 올바르게하기가 어렵다는 것을 무시하고 그냥 std::vector 또는 다른 컨테이너를 사용하십시오.

수명을보다 직접 관리해야하는 경우 std::auto_ptr (표준 라이브러리의) 및 boost::shared_ptr (부스트 라이브러리의 스마트 포인터)을 사용하십시오.이는 까다로운 평생 관리 코드를 중앙 집중화합니다. 눈에 보이지 않는 곳에서 일하는 사람은 ™입니다.

건배 &hth.

+2

정말 변수가 어디에 살고 싶은지에 달려 있습니다. 메서드 수명 동안 만 존재해야한다면 조언이 뛰어납니다. 그러나 특정 호출 체인에 존재할 수없는 변수 (호출 체인에서 반환 된 구조체 또는 객체에 객체에 대한 포인터를 저장하려는 경우)는 힙에 객체를 'new'로 할당하는 것이 가장 좋은 옵션이며, "새"척하는 것은 언제나 나쁜 선택이다. 여전히 'new'와 'delete'불일치의 가능성을 줄이는 메커니즘을 추천 한 경우 +1합니다. – sarnold

+0

@sarnold : 이제 그것에 대한 토론을 추가했습니다. 대답은 일반적으로 예를 들어 * 사용하지 않는 것입니다. '새로운'직접. 초보자들에게'new'를 사용하는 것을 권장하지 마십시오. 아주 나쁜 조언입니다. 불필요한 작업, 불필요한 복잡성 및 불필요한 버그가 발생합니다. 건배, –

+0

'std :: auto_ptr'과'boost :: shared_ptr'에 대한 탁월한 조언. :) – sarnold

2

코드를 보지 않고 누출 문제를 해결하기 위해 무엇을 해야할지 정확히 말할 수 없습니다. 당신이 소멸자를 추가 할 때

참고하지만, 그것은 당신 메모리의 양이 그 메모리를 그만큼 당신의 소멸자가 정리되지 않음을 의미하는 "간접적 손실" "확실히 손실"로에서 이동 한 것 유출 감소 모두.

대부분의 응용 프로그램 코드에서는 new을 거의 사용하지 않고 거의 new[], delete 또는 delete[]을 사용할 필요가 거의 없습니다. 일반적으로 컨테이너 (예 : std::vector)와 스마트 포인터 (예 : shared_ptr)를 사용하여 오류가 발생하기 쉬운 모든 수동 메모리 관리를 응용 프로그램에서 제거 할 수 있습니다.