2014-07-23 2 views
0

다음 코드는 간단한 해시 함수를 구현합니다. new 연산자를 사용하여 구조체 인스턴스를 할당했습니다.메모리 누수를 피하려면 delete를 사용해야합니까? new를 사용하여 구조체 인스턴스를 할당했습니다.

프로그램 종료시 delete 연산자를 사용합니까?

그렇다면 어떻게해야합니까? [delete 구조체의 각 인스턴스에 대한 설명? 아니면 더 쉬운 방법이 있습니까? ]

#include <iostream> 
#define SIZE 10 

using namespace std; 

typedef struct myhashtag 
{ 
    int data; 
    struct myhashtag * next; 
} myhash; 
void printhash(myhash array[]) 
{ 
// print fn 
} 

void hash(int data, myhash array[]) 
{ 
    int h = data % SIZE; 
    myhash * newhash = new myhash; 
    newhash->data = data; 
    newhash->next = NULL; 

    if(array[h].next == NULL) //first insert 
    { 
     array[h].next = newhash; 
     return; 
    } 
    myhash * iter = array[h].next; 
    while(iter->next != NULL) 
    { 
     iter = iter->next; 
    } 
    iter->next = newhash; 
    return; 
} 


int main() 
{ 
    myhash array[SIZE];int i; 
    for(i=0; i<SIZE; i++) 
    { 
     array[i].data = 0; 
     array[i].next = NULL; 
    } 

    while(1) 
    { 
     cout << "\nSo, what would you like to enter? : "; 
     cin >> i; 
     hash(i, array); 
     printhash(array); 
    } 

// the deletes go here 

    return 0; 
} 
+5

모든'new()'에는'delete' 문이 있어야합니다. 구조체의 각 인스턴스에 대해'delete' 문을 사용합니까? 예, myhash array [SIZE];로 자동 생성 된 것 외에도. –

+0

큰 프로젝트를 처리 할 때마다 모든 new 연산자에 대해 delete를 사용해야합니다! 그렇지 않으면 기억력이 떨어질 것입니다! – Sathish

+1

하지만 정말로''std :: shared_ptr' (http://en.cppreference.com/w/cpp/memory/shared_ptr)와 같은 메모리 관리 장치를 사용하여'new'와'delete'가 ' 필요하다. – 0x499602D2

답변

3

일반적으로 new를 사용하여 할당 할 때마다 한 번씩 삭제 (또는 삭제 [])해야합니다.

Linux를 사용하는 경우 valgrind가 메모리 누수를 감지하는 데 도움이 될 수 있습니다.

최신 버전의 C++뿐만 아니라 Boost 라이브러리는 다양한 종류의 스마트 포인터를 제공하여 객체가 더 이상 참조되지 않을 때 기본적으로 메모리를 자동으로 해제합니다.

C + + 선택 도서에서 std :: unique_ptr을 조회하십시오.

+0

감사합니다! 하지만 실제로 라이브러리를 사용하고 싶지는 않습니다. Boost는 확실히 실행 파일의 크기를 "늘릴"것입니다! [off-topic] 어쨌든'new'와 같은 방식으로'delete'가 작업을 수행해야한다고 생각합니까? – sigmasquared

+1

@sigmasquared _ '라이브러리를 사용하고 싶지 않습니다.'_ C++ 표준 라이브러리가 아니라면 필요하지 않습니다. –

+1

예, 그렇습니다. 그러나 삭제해야 할시기를 아는 것은 때로는 어렵습니다. 발신자 또는 수신자가 메모리를 확보 할 책임이 있는지 여부를 코드에 올바르게 기록해야합니다. 한 가지 규칙은 메모리가 호출자에게 속해있을 때 참조를 사용하고 호출 수신자가 소유권을 가져올 때 포인터를 사용하는 것입니다. – manuBriot

1

예 동적 메모리를 항상 삭제해야합니다.

간단한 RAII 컨테이너를 구현하여 메모리 정리를 처리 할 수 ​​있습니다. 생성자의 메모리를 알려주는 핸들로 작동하도록 클래스를 생성하면됩니다. 소멸자 내에서 그것을 삭제하고 일종의 액세스 메커니즘을 제공합니다. 그런 식으로 핸들이 선언 된 범위의 끝에서 메모리가 자동으로 정리됩니다.

+0

수업을하지 않고 다른 방법으로? 나는 로테이트로 모든 요소를 ​​반복하고 프론트 엔드에서 프런트 엔드를 삭제해야만한다고 생각합니다. – sigmasquared

+0

수업을 사용하지 않는 이유가 있습니까? C++ 클래스와 구조체 간의 유일한 차이점은 기본 액세스 수준입니다. 구조체의 기본값은 public이고 클래스는 private입니다. 그래서 구조체를 사용하여 동일한 작업을 수행 할 수 있습니다. –

1

C++에서는 개체의 수명을 관리해야합니다. 많은 Java 또는 C# 서적들이 당신을 믿게 만들 정도로 힘들지 않습니다. 그러나 예, garbage collector을 사용하지 않고 delete이 적절하게 호출되어야합니다.

내가 게시 한 코드에 대해 이렇게하는 방법은 두 가지가 있습니다. 첫 번째는 다른 사람들이 제안한대로 std::unique_ptr을 사용하는 것입니다.

두 번째는 사용자의 struct에 소멸자를 지정하는 것입니다. C#에서 struct 키워드를 자주 사용할 필요가 없지만 C++에서 종종 struct 키워드를 사용할 필요가없는 고전적인 C typedef struct ... 관용어를 사용하는 이유는 분명하지 않습니다.). 나는 다음 코드에 보관거야,하지만 난 플래그를 지정할 것이 아니라 nonidiomatic :

typedef struct myhashtag 
{ 
    int data; 
    struct myhashtag * next; 

    ~myhashtag() 
    { 
     if (next) { 
     delete next; 
     } 
    } 
} myhash; 

(당신은 여전히 ​​delete 당신이 "여기 일어날 삭제"라는 코멘트를 넣어 헤드 노드에 확인해야).

그러나이 경우 목록의 끝 부분 인 NULL에 정확히 next이 할당되어 있다고 가정합니다. 게시 한 코드는 그렇게하지만 관례에 따라 시행됩니다. 조금 더 관용적 접근 방식은 다음과 같습니다

#include <list> 
#include <iostream> 
using namespace std' 

int main() 
{ 
    list<int> list_that_the_code_was_calling_a_hash; 
    while(1) { 
     cout << "\nSo, what would you like to enter? : "; 
     cin >> i; 
     list_that_the_code_was_calling_a_hash.push_back(i); 
     if (list_that_the_code_was_calling_a_hash.size() > 10) { 
      list_that_the_code_was_calling_a_hash.pop_front(); 
     } 
     printhash(list_that_the_code_was_calling_a_hash); 
    } 
    return 0; 
} 

를 그리고 많은 사람들이 std::list 단순히 CPU 캐시와 잘 상호 작용하지 않는 std::vector 때문에 사용하는 것이 좋습니다 것입니다 :

struct hash_node { 
    int data; 
    hash_node* next; 

    hash_node(int d, n = NULL) : data(d), next(n) { } 

    ~hash_node() 
    { 
     if (next) { 
     delete next; 
     } 
    } 
}; 

void hash(int data, hash_node* array) 
{ 
    int h = data % SIZE; 
    hash_node* newhash = new hash_node(data); 

    if(array[h].next == NULL) //first insert 
    { 
     array[h].next = newhash; 
     return; 
    } 
    hash_node* iter = array[h].next; 
    while(iter->next != NULL) 
    { 
     iter = iter->next; 
    } 
    iter->next = newhash; 
    return; 
} 

훨씬 더 관용적 접근 방식이 될 것이다 .예, std::vector은 그가 컨테이너 중간에 머물러있을 때 더 많은 복사 작업을 수행합니다. 그러나 캐시를 친숙하게 사용함으로써 그 점을 보충합니다.

관련 문제