2012-02-14 17 views
5

Đối với một khuôn khổ web, tôi đã thử các phương thức ẩn danh lần đầu tiên và gặp sự cố với quản lý bộ nhớ.Phương pháp ẩn danh trong bộ nhớ rò rỉ dự án

Làm thế nào để rò rỉ bộ nhớ này (Delphi 2009) được khắc phục?

Thông điệp rò rỉ là:

13 - 20 byte: Project27 $ ActRec x 1

program Project27; 

type 
    TTestProc = reference to procedure; 

    procedure CallMe(Proc: TTestProc); 
    begin 
    end; 

begin 
    CallMe(procedure begin end); 

    ReportMemoryLeaksOnShutdown := True; 
end. 

Cùng nhắn rò rỉ "Project27 $ ActRec x 1" xuất hiện không vấn đề có bao nhiêu phương pháp nặc danh là giữa bắt đầu và kết thúc, tôi đoán rằng rò rỉ là cho loại TTestProc, không phải là các thủ tục ẩn danh riêng lẻ

program Project27; 

type 
    TTestProc = reference to procedure; 

    procedure CallMe(Proc: TTestProc); 
    begin 
    end; 

begin 

    ReportMemoryLeaksOnShutdown := True; 

    CallMe(procedure begin end); 

    CallMe(procedure var A: Integer; begin A := 42 ; end); 

end. 
+0

Điều này đã được báo cáo trong năm 2009 là ['" QC78066 Rò rỉ bộ nhớ khi sử dụng các phương thức ẩn danh trong khối ... khối kết thúc của đơn vị chương trình "'] (http://qc.embarcadero.com/wc/qcmain .aspx? d = 78066). Vẫn không cố định. –

Trả lời

15

Khi bạn khai báo một phương thức ẩn danh bên trong một thủ tục hoặc hàm, nó sẽ được dọn sạch khi thường trình đó nằm ngoài phạm vi. (Đây là một sự đơn giản, nhưng nó đủ tốt cho cuộc thảo luận hiện tại.) Vấn đề là thói quen chính của DPR không "đi ra khỏi phạm vi." Thay vào đó, trình biên dịch Delphi chèn một cuộc gọi ẩn đến System.Halt ở cuối của nó, mà không bao giờ trả về.

Vì vậy, nếu bạn viết theo cách này, bạn sẽ nhận được thông báo rò rỉ bộ nhớ. Bạn có thể sửa chữa nó bằng cách đặt sự sáng tạo phương pháp vô danh bên trong một thói quen mà thoát bình thường, như vậy:

program Project27; 

type 
    TTestProc = reference to procedure; 

    procedure CallMe(Proc: TTestProc); 
    begin 
    end; 

    procedure Test; 
    begin 
    CallMe(procedure begin end); 
    end; 

begin 
    Test; 
    ReportMemoryLeaksOnShutdown := True; 
end. 
+3

Còn nhiều điều hơn thế nữa. Nếu bạn khai báo một biến giao diện với phạm vi toàn cục trong tệp .dpr và gán cho nó, thì nó sẽ được dọn dẹp trước khi kiểm tra rò rỉ chạy. Các phương pháp Anon rõ ràng là đặc biệt. –

+1

@David: Thật kỳ quặc. Nghe như một con bọ vậy. Ai đó phải gửi báo cáo QC cho nó. –

+0

Không ai nên làm bất cứ điều gì giữa bắt đầu và kết thúc trong .dpr khác hơn là gọi một hàm được viết trong một đơn vị khác. Ngay cả việc khai báo thủ tục trực tiếp trong .dpr là một thực tế khủng khiếp, và là kiểu xấu. –

10

Tôi đoán đây là bởi vì bạn đang sử dụng chính begin..end. khối bên trong tập tin .dpr. Các cấu trúc bộ nhớ ẩn được tạo trong phạm vi begin..end. không được phát hành khi FastMM4 kiểm tra bộ nhớ, vì nó chưa nằm ngoài phạm vi.

Không có rò rỉ bộ nhớ nếu bạn đặt phương thức ẩn danh bên ngoài khối begin..end. chính này.

Lời khuyên của tôi là tránh đặt một số mã bên trong tệp .dpr - đó là phần lớn thời gian lỗi. Và IDE không thích điều đó. Sử dụng một đơn vị riêng biệt cho mã của riêng bạn và để nguyên nội dung .dpr. :)

+0

Trong khi tôi đồng ý rằng đó là lựa chọn tốt nhất cho mã không tầm thường, tôi thường đặt mọi thứ vào dpr khi kiểm tra một số thuật toán trong chương trình bảng điều khiển. Nhưng ngay cả sau đó, anonmethos và giao diện của tôi, vv là tất cả các địa phương để chức năng (trong dpr), không bao giờ trong khối chính. –