2013-05-20 44 views
5

Tôi đang mã hóa trình phân tích cú pháp XML bằng libxml2. Trên thực tế, tôi đã hoàn thành nó nhưng có một vấn đề khá khó chịu của bộ nhớ. Chương trình đầu tiên nhận được một số liên kết từ cơ sở dữ liệu của tôi và tất cả các liên kết đó trỏ đến một tệp XML. Tôi sử dụng curl để tải chúng xuống. Quá trình này rất đơn giản: tôi tải xuống một tệp, sau đó tôi phân tích cú pháp, v.v ...Rò rỉ bộ nhớ lớn với libxml2

Vấn đề có vẻ là khi phân tích xong. Curl tải xuống tệp tiếp theo nhưng dường như XML trước đó không được giải phóng, vì tôi đoán libxml2 tải nó trong RAM. Khi phân tích cú pháp XML cuối cùng, tôi thấy bản thân bị rò rỉ ~ 2.6GB (vâng, một số tệp này thực sự lớn ...) và máy của tôi chỉ có 4GB RAM. Nó hoạt động cho thời điểm này, nhưng trong tương lai, nhiều liên kết sẽ được thêm vào cơ sở dữ liệu, vì vậy tôi phải sửa nó ngay bây giờ.

Mã của tôi là rất cơ bản:

xmlDocPtr doc; 
doc = xmlParseFile("data.xml"); 

/* code to parse the file... */ 

xmlFreeDoc(doc); 

Tôi đã cố gắng sử dụng:

xmlCleanupParser(); 

nhưng doc nói: "Nó không deallocate bất kỳ bộ nhớ tài liệu liên quan" (http://xmlsoft.org/html/libxml-parser.html#xmlCleanupParser)

Vì vậy, câu hỏi của tôi là: Có ai biết cách xử lý tất cả tài liệu liên quan đến bộ nhớ này không?

+0

Nếu bạn đang tải các tập tin lớn vào bộ nhớ, tôi không hiểu lý do tại sao bạn nên ngạc nhiên khi sử dụng bộ nhớ khổng lồ. libxml2 là một đoạn mã được kính trọng sử dụng bởi nhiều hệ thống phần mềm quan trọng, tôi rất nghi ngờ có một "rò rỉ bộ nhớ lớn" với việc sử dụng chính xác libxml2. – carlosdc

+0

Làm thế nào để bạn biết có rò rỉ bộ nhớ? Có lẽ đo lường của bạn là thiếu sót ... Lưu ý rằng số liệu thống kê bộ nhớ có thể đặc biệt khó giải thích một cách chính xác. – rodrigo

+2

Hãy thử chạy nó dưới valgrind, nó báo cáo nơi bộ nhớ chưa phân bổ được cấp phát. –

Trả lời

6

Vấn đề là bạn đang nhìn vào số liệu thống kê một cách sai lầm ...

Khi một chương trình khởi động nó phân bổ một số bộ nhớ từ hệ điều hành cho các heap. Khi nó thực hiện malloc (hoặc chức năng tương tự), thời gian chạy C sẽ lấy các lát từ đống đó cho đến khi nó hết. Sau đó, nó sẽ tự động yêu cầu hệ điều hành cho bộ nhớ nhiều hơn, có thể mỗi lần trong các khối lớn hơn. Khi chương trình thực hiện free, nó đánh dấu bộ nhớ được giải phóng khả dụng cho thêm malloc s, nhưng nó sẽ không trả lại bộ nhớ cho hệ điều hành.

Bạn có thể nghĩ rằng hành vi này là sai, chương trình bị rò rỉ, nhưng không phải là: bộ nhớ giải phóng được tính, chỉ không có trong hệ điều hành mà trong lớp thư viện C của ứng dụng của bạn. Bằng chứng cho rằng đó là bộ nhớ cho tệp XML thứ hai không thêm vào tệp thứ nhất: nó sẽ chỉ đáng chú ý nếu nó là tệp lớn nhất.

Bạn cũng có thể nghĩ rằng nếu bộ nhớ này không còn được sử dụng bởi chương trình này, nó chỉ lãng phí ở đó và nó không thể được sử dụng cho các quá trình khác. Nhưng điều đó không đúng: nếu bộ nhớ không được chạm vào trong một thời gian và nó là cần thiết ở nơi khác, trình quản lý bộ nhớ ảo của hệ điều hành sẽ trao đổi nó và sử dụng lại nó.

Vì vậy, tôi đoán là thực sự bạn không gặp vấn đề gì.

PS: Những gì tôi vừa mô tả không phải lúc nào cũng đúng. Đặc biệt là nhiều thư viện C tạo ra sự khác biệt giữa các khối bộ nhớ nhỏ và lớn và phân bổ chúng một cách khác nhau.

+0

Điều này thực sự thú vị, tôi không biết điều đó. Cảm ơn bạn đã giải thích. Sau một vài thử nghiệm với valgrind, tôi có thể nói rằng bạn đã đúng. Cảm ơn bạn một lần nữa :) – Pwet

+0

Ok có thể bạn đã đúng và không có rò rỉ bộ nhớ nào cả. Nhưng thực tế là việc sử dụng bộ nhớ đang tăng lên và cuối cùng khi nó đạt gần 95% bộ nhớ hệ thống có sẵn, chương trình bị treo. Làm thế nào để giải quyết vấn đề này. Mã của tôi giống như @Pwet – crooveck

+0

@crooveck: Điều đó thường có nghĩa là một trong: A) bạn không giải phóng bộ nhớ sau khi sử dụng (bạn đang bị rò rỉ) bởi vì nếu bạn đã giải phóng nó, nó sẽ được sử dụng lại và bạn sẽ không đạt được điều đó 95%; B) bạn thực sự cần tất cả bộ nhớ đó (bạn không bị rò rỉ), ví dụ vì bạn đọc một tệp XML 8GB vào bộ nhớ, và bạn chỉ có 4GB bộ nhớ vật lý cộng với trao đổi ... và điều đó sẽ không hoạt động. – rodrigo

1

Kết thúc trò chơi nhưng chỉ tìm thấy bài đăng này ngay hôm nay. Nó có thể hữu ích cho người đọc khác nữa.

Nếu bạn phân tích cú pháp hoặc tạo tài liệu lớn, bạn có thể xem xét các API XmlReader và XmlReader. Việc sử dụng bộ nhớ giảm đáng kể, thực sự gần như sử dụng liên tục bất kể đầu vào lớn đến mức nào.

http://xmlsoft.org/html/libxml-xmlreader.html http://xmlsoft.org/html/libxml-xmlwriter.html