2010-06-14 5 views
3
std::map<int, int> * mp = new std::map<int, int>; 
for(int i = 0; i < 999999; i++){ 
    mp->insert(std::pair<int, int>(i, 999999-i)); 
} 
p("created"); 
//mp->clear();  -  doesn't help either 
delete mp; 
p("freed"); 

문제는 "delete mp"가 아무 것도하지 않는다는 것입니다. 비교하려면 :지도에서 메모리를 해제합니다. C++

std::vector<int> * vc = new std::vector<int>; 
for(int i = 0; i < 9999999; i++){ 
    vc->push_back(i); 
} 
p("created"); 
delete vc; 
p("freed"); 

메모리를 해제하십시오. 지도에서 메모리를 해제하는 방법?
PS : p ("string")는 프로그램을 일시 중지하고 입력을 기다립니다.

+3

"mp 삭제가 아무 것도하지 않음"을 어떻게 알 수 있습니까? 그리고 왜 당신은지도를 새로 만들었습니까? –

+0

"mp 삭제가 아무 것도하지 않는다"는 것을 어떻게 알 수 있습니까? - 난 그냥 작업 관리자 (리눅스에서 "상단")를보고, 나는 응용 프로그램에서 사용하는 RAM을 참조하십시오. 왜지도를 새로 만들까요? - 그냥 실험하고있어. – foret

+0

왜 이런 방식으로하고 싶습니까? – anish

답변

9

응용 프로그램에서 사용하는 RAM은 메모리가 의미 상 해제되었는지 정확하게 알 수 없습니다.

해제 된 메모리는 다시 사용할 수있는 메모리입니다. 때로는 OS가 응용 프로그램에서 사용하는 메모리로보고 한 내용에서이 해제 된 메모리를 직접 관찰하지 않아도됩니다.

언어의 의미가 그렇기 때문에 메모리가 해제되었음을 알고 있습니다.

+2

글쎄, 만약 내가 반복한다면 99999999 프로그램은 내 컴퓨터 RAM (4GB)의 15 %까지 먹을 것이다. 그래서 나는 kBytes의 RAM을 말하는 것이 아니다. 벡터를 사용하면 15 % 램 사용을 삭제 한 후 0.0 %로 떨어집니다. 지도를 사용하면 "삭제"후에 차이가 보이지 않습니다. – foret

+2

@foret : 벡터 은 하나의 인접 할당을 사용해야하는 반면, std :: map 은 많은 작은 할당 (키/값 노드 당 하나)을 사용하기 때문에 가능합니다. 4KB를 초과하는 할당이 OS에 직접 전달되는 것은 일반적입니다. – MSalters

+2

@foret : 실제로 코드를 루프에 넣고 실행하십시오. 열 번. 귀하의 경우 첫 번째 루프 반복 이후 더 이상의 메모리 증가가 발생하지 않아야합니다. – Dummy00001

2

실제로, 다음 코드는 누출하지 않는 경우

{ 
    std::map<int, int> some_map; 
} 

다음 코드 해야뿐만 아니라하지 누출 : 유형이 new로 사용 어떤이 적용

{ 
    std::map<int, int>* some_map = new std::map<int, int>(); 
    /* some instructions that do not throw or exit the function */ 
    delete some_map; 
} 

유형이 잘 쓰여지는 한. 그리고 std::map은 아마도 매우 잘 쓰여졌을 것입니다.

누출 여부를 확인하려면 valgrind을 사용하시기 바랍니다. 나는 당신이 관찰 한 것이 진짜 누설이라고 크게 의심합니다.

+0

STL 할당 체계가 미래 할당을 위해 할당 해제 된 메모리를 계속 유지할 가능성이 높습니다. –

1

메모리를 해제했는지 여부를 정확히 나타내려면 개체의 소멸자에 관찰 가능한 효과를 추가하고 관찰하십시오. 예를 들어지도 대신 소멸자가 호출 될 때 출력을 내보내는 사용자 정의 클래스를 만듭니다. 이 같은 뭔가 :

#include <map> 
#include <iostream> 
#include <utility> 

class Dtor{ 
     int counter; 
    public: 
     explicit Dtor(int c):counter(c) {std::cout << "Constructing counter: " << counter << std::endl; } 
     Dtor(const Dtor& d):counter(d.counter) {std::cout << "Copy Constructing counter: " << counter << std::endl; } 
     ~Dtor(){ std::cout << "Destroying counter: " << counter << std::endl; } 
}; 

int main(){ 
    std::map<int, const Dtor&> * mp = new std::map<int, const Dtor&>; 
    for (int i = 0; i < 10; ++i){ 
     mp -> insert(std::make_pair(i, Dtor(i))); 
    } 
    delete mp; 
    return 0; 
} 

당신은 예상대로 포인터를 삭제하면, 당신의 개체의 소멸자를 호출하는 것을 목격 할 것이다.

+0

이 작업을 수행하는 경우 할당 연산자를 포함하는 것이 유용합니다 (어쨌든 생성 될 예정 임). –

+0

@Martin : 예, 그렇습니다. 신속하게 작성된 예제입니다. IIRC 나는 단순히 소멸자와 시각적으로 일치시키기 위해 복사 생성자를 추가했다. – Francesco

2

Daniel이 언급했듯이 응용 프로그램에서 사용하는 RAM은 반드시 메모리 누수를 나타내는 지표는 아닙니다. 벡터와 관련된 동작에 관해서는 벡터가 메모리 레이아웃이 연속적임을 보장합니다. 따라서 99999999 크기의 벡터를 만들 때 모든 99999999 요소가 순서대로 배열됩니다. &은 꽤 큰 메모리 덩어리를 구성합니다. 이것을 삭제하면 프로세스 크기에 확실히 영향을 미칩니다. 맵은 다르게 동작합니다 (Wikipedia의 경우 자체 분산 이진 트리로 자주 구현 됨). 따라서 삭제하면 프로세스 메모리 공간에서 조각화가 발생할 수 있습니다. & 아마 프로세스 메모리가 즉시 삭제되지 않기 때문일 수 있습니다. 메모리 누수를 감지하는 가장 좋은 방법은 무엇이 잘못되었는지를 명확하게 나타내는 valgrind와 같은 도구를 사용하는 것입니다.

+0

위키 피 디아는 좋은 출발점이지만 참고 자료로 인용 할 수있는 좋은 곳은 아닙니다 (웨일즈 씨는이 주제에 대해 여러 번 인용되었습니다). 밸런스드 트리로 맵을 구현할 필요가 없다는 것을 보여줄 수있는 권위있는 리소스 (이 경우에는 C++ STL 컨테이너의 요구 사항)로 안내 할 수있는 좋은 장소입니다 (하지만 대부분의 구현 –

+0

@Martin - 동의 해 주셔서 감사합니다.이 사실을 명심하십시오. – Raam

관련 문제