2014-09-24 18 views
22

Khi sử dụng một vectơ vectơ rất lớn, chúng tôi đã tìm thấy một phần của bộ nhớ không được giải phóng.Huge std :: vector <std::vector> không giải phóng tất cả bộ nhớ về sự hủy diệt

#include <iostream> 
#include <vector> 
#include <unistd.h> 

void foo() 
{ 
    std::vector<std::vector<unsigned int> > voxelToPixel; 
    unsigned int numElem = 1<<27; 
    voxelToPixel.resize(numElem); 

    for (unsigned int idx=0; idx < numElem; idx++) 
     voxelToPixel.at(idx).push_back(idx); 

} 

int main() 
{ 
    foo(); 
    std::cout << "End" << std::endl; 
    sleep(30); 
    return 0; 
} 

Điều đó để lại khoảng 4GB bộ nhớ bị treo cho đến khi quá trình kết thúc.

Nếu chúng ta thay đổi dòng for để

for (unsigned int idx=0; idx < numElem; idx++) 
    voxelToPixel.at(0).push_back(idx); 

bộ nhớ được giải phóng.

Sử dụng gcc-4.8 trên máy linux. Chúng tôi đã sử dụng htop để theo dõi mức sử dụng bộ nhớ trên máy tính có RAM 100 GB. Bạn sẽ cần khoảng 8 GB RAM để chạy mã. Bạn có thể tạo lại vấn đề? Bất kỳ ý tưởng về lý do tại sao điều đó đang xảy ra?

EDIT: Chúng tôi đã thấy rằng điều đó không xảy ra trong máy Mac (với gcc hoặc clang). Ngoài ra, trong linux, bộ nhớ được giải phóng nếu chúng ta gọi foo hai lần (nhưng lại xảy ra lần thứ ba).

+1

Bạn có thể sao chép điều này bằng ví dụ nhỏ hơn không? – stefan

+0

@stefan nhỏ hơn như thế nào? trong số yếu tố? Tôi đã nhìn thấy điều này xảy ra trên 2^25, nhưng đối với nhỏ hơn nó khó nói. – quimnuss

Trả lời

27

Phân bổ nhỏ (tối đa 128kb theo mặc định, tôi nghĩ) được quản lý bởi một đống trong quá trình và không được trả về hệ điều hành khi chúng được phân phối lại; chúng được trả về đống để tái sử dụng trong tiến trình. Phân bổ lớn hơn đến trực tiếp từ hệ điều hành (bằng cách gọi mmap), và được trả lại cho hệ điều hành khi deallocated.

Trong ví dụ đầu tiên của bạn, mỗi véc tơ chỉ cần phân bổ đủ không gian cho một đơn int. Bạn có một trăm triệu phân bổ nhỏ, không ai trong số đó sẽ được trả lại cho hệ điều hành.

Trong ví dụ thứ hai, khi vectơ phát triển, nó sẽ tạo nhiều phân bổ các kích thước khác nhau. Một số nhỏ hơn ngưỡng mmap, chúng sẽ vẫn còn trong bộ nhớ quá trình; nhưng, vì bạn chỉ làm điều này với một vectơ, đó sẽ không phải là một số tiền khổng lồ. Nếu bạn đã sử dụng resize hoặc reserve để phân bổ tất cả bộ nhớ cho mỗi véc tơ trước khi điền vào nó, thì bạn sẽ thấy rằng tất cả bộ nhớ được trả về hệ điều hành.

+0

Mỗi vectơ bên trong '1 << 27' chỉ chứa một' int' duy nhất, vì vậy 'resize' /' reserve' sẽ không giúp ích gì trong trường hợp này. Có một 'thay đổi kích cỡ' cho vector bên ngoài rồi. –

+0

@MarkRansom: Rất tiếc, bạn nói đúng, tôi đã đọc sai mã. –

+0

@MikeSeymour Điều đó nghe có vẻ đúng ... bạn có biết nếu có một cách để buộc quá trình giải phóng bộ nhớ heap không sử dụng? Điều gì sẽ xảy ra nếu hệ điều hành hết bộ nhớ? – quimnuss

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