2012-02-23 27 views
8

Khi sử dụng Direct3D trong C++, tôi có thể viết một lớp "Cube" có chứa "ID3D11Buffer * vertexBuffer_" và đảm bảo rằng destructor cho đối tượng Cube đó gọi vertexBuffer _-> Release().Giải phóng tài nguyên bằng ngôn ngữ D

Tôi có thể có lớp "Cảnh" chứa đối tượng "unique_ptr cube_". Vì vậy mà tôi biết rằng khi tôi xóa cảnh của tôi, khối lập phương sẽ bị xóa, và do đó sẽ gọi phát hành trên các tài nguyên D3D mà nó đang sử dụng.

Trong D tôi không thể thực hiện việc này. Tôi có thể viết destructors nhưng tôi không có ý tưởng khi họ sẽ được gọi. Nếu GC không yêu cầu bộ nhớ, chúng có thể không bao giờ được gọi ...

Vậy cách tốt nhất để xử lý loại điều này trong D là gì? Tôi có thể thêm chức năng thành viên "miễn phí" vào mỗi đối tượng giải phóng tất cả các tài nguyên của chính nó và gọi "Miễn phí" trên bất kỳ đối tượng nào mà nó sở hữu, nhưng điều này có vẻ là một lỗi hoạt động thủ công và một bước lùi từ C++.

Có cách nào tốt hơn để xử lý loại điều này trong D?

Trả lời

6

Bạn có thể sử dụng cấu trúc trên ngăn xếp. Điều đó có sự hủy diệt xác định. Bạn thậm chí có thể có nó được refcounted bằng cách sử dụng std.typecons.RefCounted. Không sử dụng một cấu trúc trên heap mặc dù nếu bạn muốn đảm bảo rằng destructor chạy. Tại thời điểm này, tôi không nghĩ rằng destructors structs bao giờ có được chạy nếu họ đang đặt trên đống, bởi vì GC không có thông tin mà nó cần phải làm như vậy (mà nên được cố định tại một số điểm trong trong tương lai).

Nhưng nếu anh cứ khăng khăng đặt nó trong trên đống trong một lớp học, và bạn muốn tiêu diệt một cách rõ ràng các đối tượng, sau đó bạn có thể gọi clear vào nó:

clear(obj); 

Đó sẽ gọi destructor của đối tượng và sau đó đặt nó trong một trạng thái không hợp lệ, và bất cứ điều gì mà cố gắng sử dụng nó sau đó sẽ thổi lên (IIRC, bảng ảo được zeroed ra). Nhưng bộ nhớ không thực sự được giải phóng. Đó là công việc của GC. Và không sử dụng delete. Nó sẽ không được chấp nhận. Tôi thực sự ngạc nhiên rằng nó vẫn chưa được, vì nó đã được lên kế hoạch cho các lứa tuổi để thoát khỏi nó.

Và tất nhiên, một tùy chọn là có chức năng rõ ràng mà bạn gọi để giải phóng tài nguyên. Cho dù đó là một ý tưởng hay không phụ thuộc vào những gì bạn đang làm. Nhưng bất kể, các lớp học được dự định sẽ được GC thu thập và không được giải phóng bất cứ khi nào bạn chọn.

Công việc đang được thực hiện trên phân bổ tùy chỉnh, sẽ cung cấp cho bạn nhiều tùy chọn hơn về cách phân bổ lớp học và một trong số đó có thể cho phép bạn hủy lớp học xác định hơn, nhưng chưa sẵn sàng.

Và nếu bạn đang cảm thấy điên, bạn có thể sử dụng std.typecons.scoped, thay thế các loại sửa đổi sớm được phản scope (mặc dù scope đang bám xung quanh trong những bối cảnh khác - chẳng hạn như scope báo cáo). Nó đặt một lớp lên ngăn xếp.Nhưng đó là không an toàn (đó là lý do tại sao scope là đi xa trong bối cảnh này), và bạn có lẽ cũng có thể chỉ cần sử dụng một struct nếu bạn đang đi để dính các đối tượng trên stack.

EDIT: Bạn cũng có thể sử dụng mallocfree với std.conv.emplace để đưa các đối tượng trong một tổ chức phi-GC phân bổ đoạn bộ nhớ như bạn muốn có trong C++, nhưng tôi nghĩ rằng bạn sẽ phải gọi một cách rõ ràng destructor để có được nó chạy, kể từ free không hiểu về destructors (nó là một chức năng C). Điều đó sẽ có lợi thế là làm cho bộ nhớ biến mất cùng với tài nguyên (trong khi sử dụng clear trên một đối tượng trên đống GC sẽ chỉ phá hủy nội dung của đối tượng, không giải phóng bộ nhớ), nhưng tôi không biết điều đó sẽ giúp bạn nhiều qua việc sử dụng clear trên đối tượng được phân bổ GC.

Tuy nhiên, sau đó bạn có thể tạo ra một chức năng miễn phí tương tự như new mà hiện các mallocemplace cho bạn, và sau đó có một chức năng miễn phí tương tự như delete trong đó kêu gọi destructor và free, mà sẽ cung cấp cho bạn các tình huống tương tự như C++ . Trong thực tế, tôi tự hỏi nếu đó sẽ là đủ hữu ích để làm cho nó vào thư viện chuẩn. Đó có lẽ là loại điều mà sẽ kết thúc trong phân bổ tùy chỉnh mặc dù. Vì vậy, nó sẽ không làm tôi ngạc nhiên chút nào nếu trong một tương lai gần, bạn có thể sử dụng một cấp phát tùy chỉnh để làm điều gì đó như

auto obj = customAllocObj.create!MyObj(args); 
//Do stuff... 
customAllocObj.destroy(obj); 

Và tôi sẽ nghĩ rằng đó sẽ giải quyết vấn đề của bạn khá tốt cho rằng đó là cơ bản điều tương tự mà bạn muốn có trong C++, chỉ với các chức năng thư viện chứ không phải với tích hợp newdelete. Tôi nghĩ rằng tôi sẽ đưa nó lên trên nhóm tin. Tôi hy vọng rằng có ít nhất một số folks những người muốn một tính năng như vậy, và điều đó dường như phù hợp với độc đáo với phân bổ tùy chỉnh.

+0

Cảm ơn bạn đã trả lời toàn diện! Tôi không chắc tôi có thể sử dụng cấu trúc trên ngăn xếp vì đối tượng của tôi có thời lượng lâu hơn thế không. rõ ràng có thể làm việc cho tôi, nhưng nó không có vẻ khác với hàm clear() của riêng tôi. Ypu đã cho tôi nhiều điều hơn để suy nghĩ về anyway :) – jcoder

+0

@ JohnB Tôi đã giả định rằng bạn có thể sẽ đi qua các cấu trúc xung quanh, nhưng nó chắc chắn đúng rằng có thể không hoạt động, tùy thuộc vào tình hình của bạn. Nếu bạn thực hiện chức năng của riêng mình, tôi khuyên bạn không nên gọi hàm hủy trong đó - đó chỉ là yêu cầu sự cố (mặc dù hàm hủy có thể gọi bất cứ chức năng nào của bạn là giải phóng tài nguyên). Vì vậy, nếu bạn thực sự muốn gọi destructor, sau đó sử dụng 'clear'.Nếu tất cả những gì bạn muốn làm là tự do tài nguyên, thì có thể có ý nghĩa hơn khi gọi một hàm khác đặc biệt cho điều đó thay vì phá hủy đối tượng. Nó phụ thuộc vào mã của bạn. –

2

Chỉ cần làm rõ: Destructors là luôn gọi là. Nếu một đối tượng chưa được hoàn thành vào lúc ứng dụng tắt, GC sẽ chạy trình hoàn chỉnh của nó.

Tôi không thấy cách gọi thủ công một hàm free() để xóa bộ đệm đỉnh là bất kỳ lỗi nào dễ xảy ra hơn là phải quản lý bộ nhớ theo cách thủ công trong C++. Dù sao, bạn có thể muốn xem: http://www.dlang.org/phobos/std_typecons.html#scopedhttp://www.dlang.org/phobos/std_typecons.html#RefCounted

+2

Vấn đề là các trình phá hủy được gọi khi bộ nhớ được giải phóng sẽ có lúc nào đó trong tương lai khi GC nhận thấy rằng đối tượng không được nhắc đến nữa. Tôi cần các đối tượng D3D được phát hành ngay lập tức, không phải tại một số điểm không xác định trong tương lai ... – jcoder

+0

['delete'] (http://www.d-programming-language.org/expression.html#DeleteExpression)? "Nếu UnaryExpression là một tham chiếu đối tượng lớp, và có một destructor cho lớp đó, hàm hủy được gọi cho cá thể đối tượng đó." –

+0

'xóa' đang bị xóa khỏi ngôn ngữ. Không sử dụng nó. Bạn có thể sử dụng 'clear', mà sẽ gọi destructor của đối tượng và làm mất hiệu lực đối tượng, nhưng nó sẽ không giải phóng bộ nhớ. Đó là công việc của GC. Nếu bạn muốn hủy diệt xác định, sau đó sử dụng một cấu trúc. –

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