2012-04-04 44 views
10

Tôi có một plugin C# sử dụng một DLL C++ riêng biệt. Tham chiếu duy nhất cho DLL đó là từ bên trong chính plugin đó. Ứng dụng cha mẹ tải tất cả các plugin trong AppDomain của riêng họ và dỡ bỏ AppDomain này khi plugin được tải xuống.C++ DLL không tải xuống với AppDomain

Tôi đã kiểm tra và chắc chắn tôi sẽ thấy bộ nhớ của ứng dụng bị giảm khi tôi bỏ plugin. Tôi cũng có thể xóa tất cả các hội đồng quản lý đã được tải. Vấn đề là khi tôi cố gắng để xóa các DLL bản địa tôi chỉ tiếp tục nhận được truy cập bị từ chối cho đến khi tôi đóng toàn bộ ứng dụng.

Tôi đã xem xét điều này trong một thời gian, nhưng tôi vẫn không thể tìm ra lý do tại sao chỉ DLL này nằm trong bộ nhớ.

Trả lời

18

AppDomains là một cấu trúc mã được quản lý thuần túy. Không có gì giống như vậy tồn tại trong mã nguồn gốc, cũng như Windows không có bất kỳ ý tưởng nào về nó. Vì vậy, phạm vi cho một DLL bản địa nạp là quá trình. Về mặt kỹ thuật, trình khắc phục sự cố có thể tham khảo đếm DLL và theo dõi chính xác mà AppDomain đã kích hoạt tải của DLL. Tuy nhiên nó không thể cho biết liệu bất kỳ mã nguồn gốc nào đang chạy có sử dụng DLL đó hay không. Mã gốc có thể được bắt đầu bằng một cuộc gọi được thực hiện từ mã trong một tên miền khác AppDomain, có thể gián tiếp thông qua một đại biểu được sắp xếp hợp pháp.

Cảnh báo thảm họa rõ ràng nếu người quản lý AppDomain dỡ tải một DLL được sử dụng theo cách đó, đó là một điều khó chịu và không thể chẩn đoán AccessViolation. Đặc biệt khó chịu vì nó có thể kích hoạt một thời gian dài sau khi AppDomain đã được dỡ xuống.

Vì vậy, trình soạn thảo không thực hiện loại đếm đó, DLL vẫn được tải. Chỉ có bạn mới có thể đảm bảo rằng điều này không thể xảy ra, bạn có một số biện pháp kiểm soát chính xác mã nào đang chạy trong DLL và cách nó được bắt đầu. Bạn có thể buộc DLL dỡ bỏ nhưng nó yêu cầu hack. Pinvoke LoadLibrary() mình để có được một xử lý để DLL. Và pinvoke FreeLibrary() hai lần để tải nó xuống. Cả Windows lẫn CLR đều không thể thấy rằng bạn đang lừa dối. Bạn phải đảm bảo rằng không thể sử dụng DLL sau này.

+3

+1 tốt đẹp hack :-) – Yahia

+0

Hey, chỉ muốn nói cảm ơn cho câu trả lời rất rõ ràng! – user472875

5

AFAIK (dưới mui xe) DLL gốc cần được tải qua Win32 API LoadLibrary ... tải chúng trực tiếp vào bộ nhớ quá trình - trong trường hợp ứng dụng .NET không cụ thể cho AppDomain ... LoadLibrary biết hoàn toàn không có gì về AppDomain (đó là hoàn toàn NET cụ thể) ... do đó dỡ các AppDomain không nhất thiết phải dỡ bỏ DLL bản địa ...

Thú vị cuộc thảo luận liên quan đến tình trạng này:

NẾU bạn có thể thay đổi việc thực hiện các plugin tương ứng sau đó bạn sẽ thực hiện "cuối nguồn gốc ràng buộc" trong đó sẽ giải quyết vấn đề mà bạn nhìn thấy:

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