2010-08-25 34 views
8

Tôi muốn phát hiện rò rỉ bộ nhớ của chương trình C++ trong Windows. Tôi cũng đọc tài liệu trên MSDN về mermoy leak detection và tôi cũng bắt đầu sử dụng Trình phát hiện rò rỉ hình ảnh.rò rỉ bộ nhớ phát hiện trong C++ có/không có Visual Leak Detector

Tôi có nghi ngờ về báo cáo rò rỉ. Tôi đang mong đợi một tên tệp có số dòng, nhưng tôi luôn báo cáo văn bản bên dưới. Nó có tất cả các thành phần của mô tả rò rỉ (loại khối, địa chỉ bộ nhớ, dữ liệu, vv ..) ngoại trừ tên tệp và số dòng.

Nếu nó thực sự bị rò rỉ? Nếu có, bạn có biết tại sao tệp/dòng không được báo cáo không? Trong khi chờ đợi tôi đang gặp một cái nhìn cũng tại this url

Cảm ơn

 
Detected memory leaks! 
Dumping objects -> 
{4723} normal block at 0x04AFB5B8, 8 bytes long. 
Data: 2C 3F 00 00 28 3F 00 00 
{1476} normal block at 0x04AC3B58, 12 bytes long. 
Data: 00 CD CD CD EB 01 75 4C CA 3D 0B 00 
Object dump complete. 
+0

http://www.flipcode.com/archives/How_To_Find_Memory_Leaks.shtml – DumbCoder

+0

Đây là chủ đề không đúng nhưng tôi đã được khuyên trước khi sử dụng các con trỏ thông minh để tránh quản lý bộ nhớ thủ công và rò rỉ bộ nhớ – Ahmed

+0

Bạn nên sử dụng thiết bị deleaker. nó phải giúp bạn. –

Trả lời

0

Bạn nên sử dụng Valgrind, nó rất mạnh mẽ và giải thích đúng nơi là những rò rỉ nằm trong chương trình của bạn. Tuy nhiên, chương trình của bạn có thể cần phải được biên dịch bằng gcc, ...

+0

Tôi biết công cụ này nhưng tôi sợ tôi phải dính vào VC++! :) – user311906

+0

Không có gì để ngăn chặn bạn xây dựng nó trong gcc, rò rỉ là như nhau bất cứ điều gì trình biên dịch – Patrick

+3

giả sử ứng dụng của mình + thư viện ông sử dụng tương thích với cả linux/gcc và windows/vC++ –

5

Đây là đầu ra từ CRT gỡ lỗi của Visual Studio, chứ không phải đầu ra từ Trình dò ​​tìm rò rỉ trực quan. Trước tiên, hãy đảm bảo rằng bạn đang sử dụng phiên bản hiện tại tại Codeplex và bạn đã #included vld.h trong dự án của mình. Bạn sẽ nhận được một đầu ra nhiều thông tin hơn.

+0

Xin chào! Thật không may là đầu ra của Visual Leak Detector. Tôi đang sử dụng một phiên bản cũ lấy từ trang web CodeProject không phải là một từ CODEPLEX .. vì vậy tôi đoán rằng tôi nên cập nhật + Tôi sẽ kiểm tra thiết lập. QUAN TRỌNG: bạn có thể nhẹ nhàng xác nhận rằng những gì tôi đã viết là một sự rò rỉ thực sự không? – user311906

+0

Đó không phải là đầu ra của Visual Leak Detector - bạn sẽ nhận được rất nhiều đầu ra với các trang gọi là nơi các đối tượng được phân bổ. Bạn đang thấy đầu ra của bộ dò tìm rò rỉ Visual Studio: http://msdn.microsoft.com/en-us/library/e5ewb1h3%28VS.80%29.aspx –

0

Rational Purify có sẵn dưới dạng plugin tiền cho VC++ và là trình phát hiện rò rỉ rất tốt (và sự cố khác). Tôi đã từng sử dụng nó rất nhiều trên Solaris, và nó là rất dễ sử dụng và rõ ràng. Tôi cũng đã nghe những điều tốt đẹp từ những người khác về phiên bản để sử dụng với Visual Studio, nhưng tôi chưa bao giờ thực sự thử điều đó.

FWIW, tôi nghi ngờ rằng Purify là nguồn cảm hứng cho Valgrind, đã được đề cập đến.

0

Nếu số phân bổ (số trong dấu ngoặc ôm) luôn giống nhau, this could help. Về cơ bản, nó mô tả làm thế nào để làm cho VC + + tạo ra một breakpoint khi phân bổ với số quy định là cố gắng.

+0

Xin chào SpaceComboy, Cảm ơn bạn! Tôi nhận thấy rằng; Tôi thấy rằng trong một số dự án, nó vẫn giữ nguyên và trong các thay đổi khác. – user311906

+0

@ user311906: Các số phân bổ chỉ là đếm tất cả các phân bổ đống được tạo. Nếu ứng dụng của bạn thực hiện phân bổ theo cùng thứ tự mỗi lần, số lượng phân bổ bị rò rỉ sẽ không thay đổi và bạn có thể sử dụng nó để theo dõi nguồn gốc của vấn đề. Điều này thậm chí còn hữu ích hơn chỉ là tệp và số dòng, vì nó cũng sẽ cung cấp cho bạn trạng thái hiện tại của ứng dụng. –

7

Tôi đã nghiên cứu một số cách khác nhau để theo dõi rò rỉ bộ nhớ. Tất cả đều có lợi thế của họ mà còn bất lợi của họ.

Để hiểu những ưu điểm và nhược điểm của họ, chúng ta phải hiểu được cơ chế và các yêu cầu khác nhau:

  1. như thế nào mới, xóa, malloc và free chặn? Một số công cụ sử dụng #define để xác định lại mới, xóa, malloc và miễn phí, nhưng điều này dựa vào thứ tự đúng của các tệp bao gồm và có thể gây ra sự cố nếu một lớp có chứa e.g. một phương thức được gọi là miễn phí (như trường hợp trong Qt). Bộ tiền xử lý cũng sẽ xác định lại phương thức này, điều này có thể dẫn đến lỗi biên dịch hoặc các phần tử bên ngoài chưa được giải quyết.

    Cách khác là ghi đè toán tử mới và xóa toàn cầu. Đây là một giải pháp sạch hơn nhiều, nhưng thất bại là bạn có một thư viện của bên thứ ba đặt một thư viện mới trong thư viện, nhưng xóa trong tiêu đề (hoặc ngược lại).

  2. Nguồn của cuộc gọi được xác định như thế nào. Nếu mới, xóa, ...bị chặn bằng cách sử dụng # define's, thường là các ký hiệu tiền xử lý __FILE____LINE__ được sử dụng để lấy nguồn rò rỉ. Tuy nhiên, nếu bạn có các hàm 'chung' trong mã của mình, ví dụ: CreateString(), sau đó hầu hết các rò rỉ sẽ được báo cáo trong các hàm chung này, điều này không thực sự giúp bạn.

    Cách khác là nhận cuộc gọi ngăn xếp trong thời gian chạy. Nó có thể khá dễ dàng thực hiện bằng cách sử dụng chức năng Windows StackWalk, nhưng theo kinh nghiệm của tôi, điều này là rất rất chậm. Một cách thay thế nhanh hơn nhiều là lấy trực tiếp con trỏ cơ sở và dựa vào các con trỏ khung-chồng (bạn phải biên dịch với/Oy- để lấy các con trỏ-khung-con trỏ). Bạn có thể lấy con trỏ khung (cơ sở) như thế này: _asm mov DWORD PTR [FramePtr], ebp. Sau đó, chỉ đơn giản là vòng lặp và trong vòng lặp có được con trỏ hướng dẫn từ ((ADDR *)FramePtr)[1]; và con trỏ khung kế tiếp từ FramePtr = ((ADDR *)FramePtr)[0];

  3. Cách báo cáo rò rỉ tại thời điểm chính xác. Trong trường hợp của tôi, tôi muốn các rò rỉ được báo cáo vào cuối của ứng dụng, nhưng để có thể làm điều này, bạn cần một cơ chế báo cáo rò rỉ ở phần cuối của ứng dụng của bạn. Điều này có nghĩa rằng nếu bạn muốn tự mình báo cáo rò rỉ, bạn cần phải dựa vào các biến toàn cầu bị hủy ở cuối ứng dụng của bạn (và báo cáo các rò rỉ trong phần tử hủy của biến toàn cục). Đối với các ứng dụng kiểu máy chủ, bạn có thể quan tâm nhiều hơn đến việc nhận được sự khác biệt về mức sử dụng bộ nhớ giữa hai điểm trong thời gian.

Và bây giờ rò rỉ-hệ thống khác nhau:

  1. C RunTime: Báo cáo rò rỉ ở cuối, nhưng không có cách nào phong nha của báo cáo ngăn xếp cuộc gọi. Phương pháp chặn cuộc gọi đến mới, xóa, ... có thể gây ra sự cố kết hợp với thư viện của bên thứ 3 (như Qt, Boost, ...)

  2. Tiện ích Microsoft bên ngoài (như GFlags, UMDH ,, ...): họ dường như chỉ có thể ghi lại sự khác biệt giữa hai điểm trong thời gian. Tuy nhiên, stack cuộc gọi có vẻ tốt hơn nhiều, mặc dù tiện ích GFlags có thể đặt cờ trong hệ điều hành có thể gây ra sự chậm trễ nghiêm trọng cho ứng dụng của bạn.

  3. Trình phát hiện rò rỉ hình ảnh. Dường như tìm thấy chính xác tất cả các rò rỉ, nhưng trong trường hợp của tôi nó không hoạt động vì tôi có một bên thứ 3 DLL mà chỉ đơn giản là hủy bỏ quá trình tại DllUnload của nó (có vẻ là một vấn đề cụ thể của Windows 7).

  4. Yêu thích cá nhân của tôi (và mọi người sẽ không đồng ý với tôi, tôi chắc chắn), là viết trình quản lý bộ nhớ của riêng bạn. Việc chặn có thể dễ dàng thực hiện bằng cách sử dụng toán tử mới và xóa toàn cầu (với các vấn đề có thể được đề cập ở trên), và bạn có thể nhận được ngăn xếp cuộc gọi như được mô tả ở trên. Lựa chọn này cũng dựa vào việc có thể có mã được thực hiện tại thời điểm cuối cùng trong ứng dụng của bạn.

Khi chọn một sự thay thế, tôi tìm thấy những khía cạnh sau đây rất imporant cho hoàn cảnh của tôi:

  • Tôi muốn nó hoạt động seemlessly trong ứng dụng của tôi, để mỗi nhà phát triển sẽ được thông báo ngay lập tức nếu có một rò rỉ. Nếu bạn trì hoãn kiểm tra rò rỉ đến một thời điểm sau đó, nơi bạn sử dụng các tiện ích bên ngoài như Purify, phát hiện rò rỉ sẽ khó khăn hơn nhiều.
  • Tôi muốn tự động báo cáo rò rỉ ở cuối ứng dụng.
  • Tôi muốn càng nhiều càng tốt thông tin nhất có thể từ rò rỉ (các dữ liệu, các cuộc gọi stack, ...)

Hope this helps.

2

Ok. Tôi đã nhận được nó sau khi gỡ lỗi rất nhiều tập tin tiêu đề.

Đây là những gì mà phải được thực hiện để cho phép số lượng tập tin/dòng trong đầu ra

"#define _CRTDBG_MAP_ALLOC"

"#define _CRTDBG_MAP_ALLOC_NEW"

+0

vì lý do nào đó mà hai định nghĩa chỉ cho tôi biết: c: \ program files (x86) \ microsoft visual studio 10.0 \ vc \ include \ crtdbg.h (1116): {640} khối bình thường ở 0x000A5E28, dài 12 byte. ngoài rò rỉ ... nó không thực sự giúp thiết lập –

+0

điều này gây nên cảnh báo này: c: \ program files \ microsoft visual studio 9.0 \ vc \ include \ crtdbg.h (1203): cảnh báo C4985: 'operator new' : thuộc tính không xuất hiện trên khai báo trước – Arthur

1

Bạn đã biên dịch với thông tin gỡ lỗi kích hoạt và đảm bảo rằng tệp pdb có sẵn bằng trình dò ​​tìm rò rỉ? Nếu không có thông tin này, nó sẽ không thể cung cấp số dòng.