2012-07-26 3 views
1

C/C++에서는 함수가 끝나기 전에 new/malloc 메모리가 delete/free이되어야한다고하는 상식 인 것 같습니다. 맞습니까?'new/malloc'이 '삭제/해제'해야합니까?

그러나이 consumer이 후자의 이러한 버퍼를 소비 할 또 다른 기능,

void reader(ifstream &ifs) 
{ 
    char *buf = new char[100]; 
    ifs.read(buf, 100); 
    save_buffer(buf); //save this buf into a global array, say buf_array[10] 
} 

void consumer() 
{ 
    for(int i = 0; i < 10; i++) 
     consume(buf_array[i]); //do something with those buffers read by reader 
} 

내 문제가, 나, 버퍼로 파일에서 청크를 읽어들이는 기능 reader이 이런 종류의 문제가 있다고 가정 많은 메모리 리소스는 reader 안에 new이 있지만 readerconsumer에 의해 사용되지 않았기 때문에 delete 수 없습니다. 해당 버퍼를 delete에 대해 consumer 담당해야합니까?

+0

C++ 11을 사용하는 경우 이동 의미론이 도움이 될 수 있습니다. –

+0

@VaughnCato, 고마워,하지만 지금은 사용하지 않을거야. – Alcott

+0

저는 누가 책임이 있는지 명확하게 밝히는 것이 좋습니다. 누가 언제든지 메모리를 소유하고 있습니다. 소유권이 이전되고 있음을 나타 내기 위해 "acquire"및 "release"와 같은 단어가 포함 된 이름을 사용할 수 있습니다. 소유자는 메모리가 해제되었는지 확인해야합니다. –

답변

4

메모리를 할당하는 함수는 메모리를 확보해야한다고 말한 사람은 없습니다. 그러나 일반적으로 동일한 구성 요소가이를 처리해야합니다. readerconsumer이 쌍을 이루기 때문에 메모리를 함께 조정하는 것이 좋습니다.

1

은 함수가 완료되기 전에 일부 메모리 오른쪽을 delete/free해야 new/malloc 기능, 즉 C/C++의 상식 것 같다?

아니요, 이것이 사실 일 필요는 없습니다. 프로그램이 끝나기 전에 메모리를 해제해야만 같은 기능으로 메모리를 해제 할 필요가 없습니다.

C++에서 사용할 수있는 일반적인 솔루션 중 하나는 소멸자에서 메모리를 할당 해제하는 것입니다. 복사/이동 생성자와 할당 연산자를 올바르게 처리하면서 동적으로 할당 된 메모리를 포함하는 객체를 전달하면 소멸자가 호출 될 때 메모리가 해제됩니다.

+0

소멸자에서 메모리를 해제하려면, 데이터 멤버 인'char * buffers'를 가지고 있어야하지만, 프로그램 실행 중에 얼마나 많은 버퍼가 할당되었는지는 확인할 수 없습니다. 하나 이상의 버퍼가있을 수 있습니다. 그래서 소멸자에서'delete buffers' 또는'delete [] buffers'를 사용해야합니까? – Alcott

+0

@Alcott 아이디어는 malloc 화 된 데이터를'std :: string'에서 행해지는 방식으로 자체 객체에 첨부하는 것입니다. 여러 버퍼를 할당하면 버퍼 당 하나씩 여러 객체를 만듭니다. 다시 말하면,'std :: string'은 그 기술의 아주 좋은 예입니다. – dasblinkenlight

+0

프로그램을 종료하기 전에 메모리를 해제 할 필요는 없습니다. 중요한 것은 프로그램이 실행되는 동안 메모리가 손실되지 않는다는 것입니다 (앱이 종료되기 전에 모든 메모리를 공개하는 것은 종종 잘못입니다. '매우, 매우, 매우 어렵습니다', (사용하지 않으려 고 함) 'i'word :) –

1

"모든 new에 대해 delete이 있어야합니다"라는 원칙이 있습니다. 그것은 두 함수가 같은 함수 내에 있어야한다는 것에 대해서는 아무 것도 말하지 않습니다 (분명히 유용하지는 않습니다).

독자 할당 및 소비자 해방에 대한 예제에는 아무런 문제가 없습니다.

+0

어떨까요?'reader'는'class A'의 멤버 함수이고, 메모리를 할당하고,'consumer'는'class B'의 멤버 함수이고, 메모리를 해제합니다. 괜찮아요? – Alcott

+0

네, 괜찮아요. –

+0

그렇게하고 싶다면 std :: auto_ptr을 통해 전달하여 소유권이 이전되고 있음을 분명히하십시오. – JRG

1

new/malloc (할당)과 delete/free (출시)을 동일한 기능으로 수행 할 필요가 없습니다. 알고리즘이 모든 할당이 해제되고 메모리 누출을 일으키지 않도록 한 번만 릴리스된다는 것을 보장하는 한 괜찮습니다.
실제로 종종 할당과 릴리스가 별도의 기능으로 존재합니다.
다음을 기억하십시오 :
1. 릴리스를하기 위해 동일한 포인터를 사용하십시오 (당연히 포인터를 전달할 수 있습니다). 포인터에 대해 산술 연산을 수행 한 다음 해당 수정 된 포인터를 사용하여 할당을 해제하면 포인터가 여전히 할당 영역을 가리키는 경우에도 오류가 발생합니다.
2. 위에서 언급 한 바와 같이 할당이 해제되었음을 보장해야합니다. 추가 릴리스로 인해 오류가 발생합니다.

1

버퍼에 대한 포인터를 가지고 다니는 한 초기화 된 동일한 함수에서 할당 된 버퍼를 해제 할 필요가 없습니다.

고객님의 경우 consumer으로 할당 된 버퍼는 delete입니다. 귀하의 경우에는 consumer()이 책임 져야합니다.

2 차 질문에 대해 소비자는 버퍼가 끝나는 위치를 알지 못합니다. 당신은 어떻게 든 그것을 말할 필요가 있습니다. 버퍼에 포인터를 저장하는 대신 버퍼와 버퍼 길이를 모두 캡슐화하는 새로운 struct을 정의하는 것이 좋습니다. 이것은 이미 완료되었습니다 : std::string을 사용하여보십시오. 다른 사람에

1

약간 다른 답 :

독자가/무료 읽기 기능의 메모리를 삭제하지만 소비자가 메모리를 삭제하지 않았을하지에 대한 예는 괜찮습니다. 간단한 경우 작동하지만 여러 소비자가있는 경우 (예 : 다른 형식으로 출력하는 경우) 데이터를 소비하는 것이 부작용이 있다면, 주먹 소비자가 한 후에 데이터로 다른 것을 할 수 없습니다.

필자가 명시 적으로 버퍼 정리를 호출 할 때 내 독자에게 cleanup() 형식의 메서드가 있어야합니다. 이렇게하면 메모리를 할당하는 모듈이 메모리를 확보 할 책임이 있습니다 (다른 방법 인 경우에도 해당).

Data d = Reader.read(); 
Consumer1.consume(d); 
Consumer2.consume(d); 
Reader.cleanup(d); 
// d is no longer valid. 
+0

That'r right, :-) – Alcott

+0

그런 경우, 아마도 심판을 추가하십시오. N 처리기에 게시하기 전에 개체에 N을 셉니다. 핸들러는 객체의 release() 메소드를 호출합니다. 완료 할 마지막 핸들러는 객체를 release() 및 delete()에서 0으로 계산합니다. 가능한 경우 shared_ptr이이를 수행합니다. 명시 적으로 refCount해야하는 경우 dec에 원자 단위 명령을 사용해야 할 수도 있습니다. AFAIK, shared_ptr은 스레드로부터 안전합니다. –

1

당신은 실제로 소비자를 공급하는 글로벌 배열 buf_arrray에 버피의 내용을 복사합니다. 위의 예제에서 독자는 buf를 해제 할 수 있습니다.

그리고 새로운/mallocs가 메모리를 확보해야한다는 것은 요구하지 않습니다. 포인터를 전달할 수 있습니다. 마지막으로 할당 된 메모리를 사용하는 함수는 메모리를 해제해야합니다.

0

또한 http://www.boost.org/doc/libs/1_35_0/libs/smart_ptr/shared_array.htm

공유 배열을 사용하여, 당신은 함수 내에서 그들에게 할당하고 다른 함수 값으로 전달할 수있는 공유 배열에 대해 읽을 수 있습니다. 공유 배열은 참조 된 횟수에 대한 내부 카운트를 유지하고 모든 참조가 범위를 벗어 났을 때 자동으로 메모리를 삭제합니다.

우선 순위를 내림차순으로 예를 들어

void bar(boost::shared_array<int>); 

void foo() 
{ 
    boost::shared_array<int> x (new int[ 100 ]); 
    bar(x); 
    // because x has been passed to bar(), its reference count is incremented 
    // and it will not only be deleted when everyone is finished with it! 

    // do more things with x 
} // the memory held by x is deleted 

void bar(boost::shared_array<int> y) 
{ 
    // Do things with y here 
} // the memory held by y is not deleted here because foo() hasn't yet finished 
0

당신이 선호하는 것 :

  1. 사용 auto 스토리지 클래스, 그래서 삭제가 자동으로 발생합니다.
  2. 동일한 코드에서 개체를 할당하고 삭제하십시오.
  3. 소유권을 전달하므로 한 구성 요소가 할당되고 다른 구성 요소는 해제됩니다.
  4. shared_ptr과 같은 것을 통해 공유 된 소유권을가집니다.

3과 4는 거의 연결되어 있지만, 모두가이 경우 1.

뒤에 꽤 방법 인, 2 뒤에 꽤 방법입니다, 당신이 정말 를 원합니다하는 수준입니다 함수 (또는 클래스 등)) 생산자와 소비자 모두 위의 버퍼를 할당 생산자와 소비자를 시작하고 모두 완료되면 버퍼를 삭제하려면 :

class buffer { 
    std::vector<char> data; 
public: 
    buffer() : data(100) {} 
}; 

process_file(std::string const &name) { 
    std::vector<buffer> buffers(10); 

    std::ifstream in(name); 

    std::pair<std::ifstream *, std::vector<buffer> *> thread_data = { 
     &in, &buffers 
    }; 

    prod = start_thread(producer, (void *)&thread_data); 
    cons = start_thread(consumer); 
    join(prod); 
    join(cons); 
} 

이 할 수 있다면, 그것은 두통의 많은을 방지하는 데 도움이 될 수 있습니다 기억 관리에.