2016-06-02 22 views
10

Trong chương trình thử nghiệm sau đây, bộ nhớ được phân bổ bởi std::map không được phân bổ lại. Tất cả trong tất cả chúng tôi phân bổ khoảng 2,2 GB bộ nhớ, mà không bao giờ được phát hành, mặc dù chúng tôi làm một trao đổi với một container rỗng.Tại sao std :: map < std::map > không deallocate bộ nhớ?

Khi thay đổi std::map<std::map> để trở thành std::map<std::vector>, bộ nhớ thực sự được phát hành.

Tôi đã kiểm tra mã với valgrind, điều này thật sự không tìm thấy bất kỳ rò rỉ nào.

Tại sao trường hợp này xảy ra và làm cách nào để thay đổi hành vi?

#include <cstdlib> 
#include <iostream> 
#include <vector> 
#include <map> 
#include <chrono> 
#include <thread> 

class Test 
{ 
    public: 
    std::vector< std::pair< int, int > > myContainer; 
    std::map<int,int> myMap; 

    Test(){ 
     for(int i = 0 ; i < 10000; i++ ){ 
     std::pair<int, int> pair = std::make_pair<int, int>(rand(), int(i)); 
     //myContainer.push_back(pair); 
     myMap.insert(pair); 
     }    
    } 
}; 

int main() 
{ 

    std::map<int,Test> myContainer1; 

    for(int i = 0 ; i < 5000; i++ ){  
     myContainer1.insert(std::make_pair<int, Test>(rand(), Test())); 
    }  

    std::cout << "ready!" << std::endl; 
    std::this_thread::sleep_for(std::chrono::milliseconds(5000)); 
    std::cout << "cleaning..." << std::endl; 

    { 
     std::map<int,Test> tmp; 
     myContainer1.swap(tmp); 
    } 

    std::cout << "cleaning ready!" << std::endl; 
    std::this_thread::sleep_for(std::chrono::milliseconds(15000)); 

    return 0; 
} 
+3

Bạn xác định bộ nhớ không được giải phóng như thế nào? –

+1

Tôi đã sử dụng một màn hình hệ thống, kích thước bộ nhớ thường trú. Khi sử dụng 'map < vector >' Tôi thấy rằng quá trình RSS giảm xuống còn vài MB. Khi sử dụng 'map ', RSS vẫn ở mức 2 GB. – bicu

+0

@ bicu không nhất thiết có nghĩa là bộ nhớ không được phát hành (mặc dù RSS * là * * thường * chỉ báo tốt hơn so với VSIZE). 'valgrind' thường sẽ báo cáo (trong số những thứ khác) bao nhiêu bộ nhớ vẫn được cấp phát ở cuối chương trình và đáng tin cậy hơn nhiều so với việc xem số liệu thống kê theo dõi tài nguyên. Bạn thấy những giá trị nào? – Andrew

Trả lời

10

nội bộ của std::map sử dụng màu đen/cây màu đỏ để lưu trữ các đối tượng, trong đó có nhiều đối tượng nhỏ, nhưng std::vector cửa hàng đối tượng liên tục, sử dụng một khối bộ nhớ phẳng lớn.

glibc duy trì loại bộ nhớ khác nhau.

Khi yêu cầu các đối tượng nhỏ, thường bộ nhớ được sử dụng để tránh các đoạn bên ngoài, nhưng sẽ gây ra các mảnh bên trong khi đối tượng được giải phóng và các mảnh bên trong sẽ không bao giờ trở lại hệ thống.

Khi yêu cầu các khối lớn, glibc phân bổ một khối bộ nhớ lớn, có thể chứa các đoạn bên ngoài. nhưng khi được giải phóng, bộ nhớ sẽ trở lại hệ thống.

Các vấn đề liên quan