2012-06-11 13 views
8

Tôi có một struct trông như thế này:bộ nhớ miễn phí được sử dụng bởi một std :: string

struct queue_item_t { 
    int id; 
    int size; 
    std::string content; 
}; 

Tôi có một std::vector<queue_item_t> đó là dân cư với nhiều trong số này từ một truy vấn cơ sở dữ liệu.

Khi mỗi mục được xử lý, một tệp được đọc từ đĩa và nội dung của nó được đưa vào thành viên chuỗi content. Mục được xử lý (content được phân tích cú pháp) và tôi thực thi .clear() trên chuỗi để không ăn hết bộ nhớ của mình.

Tuy nhiên, điều này dường như không giải phóng bộ nhớ. Tôi có hàng trăm ngàn mặt hàng đang được xử lý và cuối cùng, việc sử dụng bộ nhớ sẽ vượt ra ngoài những gì có sẵn và ứng dụng bị giết bởi Linux với "Out-Of-Memory" là lý do.

Làm cách nào để giải phóng bộ nhớ được sử dụng bởi các chuỗi này?

+0

bạn có cần 'nội dung' làm thành viên của cấu trúc không? Từ lời giải thích của bạn, có vẻ như nó chỉ được sử dụng rất ngắn gọn, nên tạm thời có thể phù hợp hơn với nhiệm vụ. Ngoài ra, tại sao không sử dụng 'std :: queue' thay vì' std :: vector'? –

+0

Thực tế là cấu trúc của bạn được gọi là 'queue_item_t' cho thấy rằng vector của chúng đại diện cho một số loại hàng đợi. Nếu đúng như vậy, tại sao bạn không xóa các phần tử khỏi hàng đợi khi chúng được xử lý?Tôi hỏi bởi vì nó có thể là sửa chữa thích hợp cho vấn đề của bạn nằm ở nơi khác. Phá hủy chúng (và chuỗi nội dung 'của chúng) là một cách khá chắc chắn để giải phóng tài nguyên của chúng! Sau đó, bạn chỉ cần phải đối phó với thực tế rằng việc loại bỏ từ đầu của một véc tơ không hiệu quả - vì vậy hãy sử dụng 'deque' thay vào đó, hoặc nếu thứ tự chúng được xử lý không quan trọng thì xử lý theo thứ tự ngược lại. –

+0

@SanderDeDycker phần tôi đang làm bây giờ chỉ là phần thứ hai của toàn bộ quá trình; trong hoạt động bình thường, dữ liệu không bao giờ được đọc từ các tệp nhưng được truy xuất từ ​​Internet và dữ liệu được đặt trực tiếp trong chuỗi 'nội dung' của từng mục đã được tải xuống. Nhưng bạn đúng, trong hoàn cảnh khác, một biến tạm thời sẽ tốt hơn. –

Trả lời

15

std :: chuỗi và std :: vector không thay đổi dung lượng vùng chứa (=> không giải phóng bộ nhớ vùng chứa) trong rõ ràng(). Bí quyết dưới đây với đối tượng tạm thời nên được sử dụng bất cứ khi nào nén được yêu cầu (thông thường nó không bắt buộc).

my_queue_item.content.clear(); // clear 
std::string(my_queue_item.content).swap(my_queue_item.content); // compact 

trên mã có thể được thực hiện đơn giản hơn khi dọn dẹp + nén được requried:

std::string().swap(my_queue_item.content); 

Triển khai một số chuỗi là copy-on-write. Chuỗi như vậy, khi được giới thiệu từ nhiều nơi, sẽ phân bổ lại bộ nhớ khi viết.

+0

-1 Tôi không tin câu đầu tiên của bạn là chính xác. Làm thế nào để bạn biết không có bộ nhớ được phát hành trong 'rõ ràng'? Nó có lẽ là trong thực tế. Trong nội bộ, một chuỗi có 'char *'. Khi bạn gán giá trị khác cho một chuỗi, giá trị cũ sẽ được thay thế. Nếu không có một bộ nhớ phát hành, std :: string sẽ bị rò rỉ bộ nhớ, mà nó không. –

+7

Và C++ 11 thêm chức năng thành viên 'shrink_to_fit', là một yêu cầu không ràng buộc để thực hiện để làm điều gì đó hợp lý. –

+4

@Luchian: 'clear' được đảm bảo không làm giảm' dung lượng' của chuỗi, vì vậy nó khá nhiều không thể giải phóng bộ nhớ. –

1

clear sẽ không miễn phí tất cả bộ nhớ của chuỗi (có thể chỉ là bộ đệm). Nó sẽ chỉ thiết lập chuỗi thành một chuỗi rỗng.

Nếu bạn có thể gọi clear trên chuỗi, tại sao lại không sử dụng lại? Vì vậy, thay vì tạo một queue_item_t mới, chỉ cần thay thế thành viên chuỗi của nó bằng giá trị mới.

0

clear có thể không giải phóng bộ nhớ. Nó sẽ thiết lập một chuỗi logic thành một chuỗi rỗng, nhưng có thể không ảnh hưởng đến bộ nhớ đã được cấp phát.

Nếu bạn đang đọc nhiều dữ liệu hơn vào cùng một queue_item_t, nó sẽ thay thế nội dung chuỗi trước đó.

Bạn có chắc chắn bạn không tự rò rỉ queue_item_t không?

1

Để giải phóng bộ nhớ bạn có thể làm chỉ là:

my_queue_item.content = ""; 
my_queue_item.content.shrink_to_fit(); 

Phương pháp này shrink_to_fit() sẽ nhớ độc đáo miễn phí và phân bổ không gian đủ nhỏ so với giá trị mới của my_queue_item.content (15 byte cho trường hợp này).

+1

Thật không may shrink_to_fit() là không ràng buộc vì vậy cũng có thể chỉ được bỏ qua, mà làm cho nó có vẻ là một chức năng khá vô nghĩa khi nó có thể có được một rất hữu ích. –

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