2012-02-09 26 views
12

Tôi vô cùng bối rối về quản lý tài nguyên trong C++/CLI. Tôi nghĩ rằng tôi đã có một xử lý (không có ý định chơi chữ) trên nó, nhưng tôi tình cờ gặp lớp auto_gcroot<T> trong khi xem qua các tệp tiêu đề, dẫn đến tìm kiếm trên google, sau đó là phần tốt hơn trong tài liệu đọc ngày và giờ đã nhầm lẫn. Vì vậy, tôi figured tôi muốn chuyển sang cộng đồng.C++/CLI Confusion Management Confusion

Câu hỏi của tôi liên quan đến sự khác biệt giữa ngữ nghĩa auto_handle/stack và auto_gcroot/gcroot.

  1. auto_handle: Hiểu biết của tôi là điều này sẽ dọn sạch đối tượng được quản lý được tạo trong chức năng được quản lý. Sự nhầm lẫn của tôi là không phải người thu gom rác phải làm điều đó cho chúng tôi? Đó không phải là toàn bộ điểm của mã được quản lý sao? Để cụ thể hơn:

    //Everything that follows is managed code 
    void WillThisLeak(void) 
    { 
        String ^str = gcnew String ^(); 
        //Did I just leak memory? Or will GC clean this up? what if an exception is thrown? 
    } 
    
    void NotGoingToLeak(void) 
    { 
        String ^str = gcnew String^(); 
        delete str; 
        //Guaranteed not to leak, but is this necessary? 
    } 
    
    void AlsoNotGoingToLeak(void) 
    { 
        auto_handle<String ^> str = gcnew String^(); 
        //Also Guaranteed not to leak, but is this necessary? 
    } 
    
    void DidntEvenKnowICouldDoThisUntilToday(void) 
    { 
        String str(); 
        //Also Guaranteed not to leak, but is this necessary? 
    } 
    

    Bây giờ điều này sẽ có ý nghĩa với tôi nếu nó là một sự thay thế cho C# sử dụng từ khóa, và nó chỉ được khuyến cáo để sử dụng với các loại tài nguyên-chuyên sâu như Bitmap, nhưng isnt này đề cập bất cứ nơi nào trong các tài liệu nên im ive sợ bị rò rỉ bộ nhớ toàn bộ thời gian này ngay bây giờ

  2. auto_gcroot

tôi có thể vượt qua nó như một tham số để một hàm có nguồn gốc? Điều gì sẽ xảy ra trên bản sao?

void function(void) 
    { 
     auto_gcroot<Bitmap ^> bmp = //load bitmap from somewhere 
     manipulateBmp(bmp); 
     pictureBox.Image = bmp; //Is my Bitmap now disposed of by auto_gcroot? 
    } 

    #pragma unmanaged 

    void maipulateBmp(auto_gcroot<Bitmap ^> bmp) 
    { 
     //Do stuff to bmp 
     //destructor for bmp is now called right? does this call dispose? 
    } 

Điều này có hiệu quả không nếu tôi sử dụng gcroot?

Hơn nữa, lợi thế của việc có auto_handle và auto_gcroot là gì? Có vẻ như họ làm những việc tương tự.

Tôi phải hiểu nhầm điều gì đó để điều này có ý nghĩa rất ít, do đó, một lời giải thích tốt sẽ là tuyệt vời. Ngoài ra bất kỳ hướng dẫn nào liên quan đến việc sử dụng thích hợp các loại này, nơi tôi có thể tìm hiểu công cụ này và mọi thực tiễn/địa điểm tốt hơn tôi có thể tìm thấy chúng sẽ được đánh giá cao.

thanks a lot, Max

+0

tôi không bao giờ sử dụng hầu hết trong các hình thức ở đây: Tôi luôn luôn sử dụng tài liệu tham khảo cho các đối tượng được quản lý và tôi luôn luôn để cho các GC sạch chúng cho tôi. Đôi khi tôi sử dụng 'gcroot', nhưng hiếm khi (khi tôi muốn ví dụ. Để bọc .NET đóng cửa/đại biểu vào đối tượng chức năng C++ và chắc chắn để giữ một xử lý miễn là tôi cần nó). –

+0

Đó là một nỗ lực khá sai lầm để đưa auto_ptr <> vào thế giới được quản lý. Ngớ ngẩn như thư viện STL/CLR. Điều tốt nhất cần làm là quên đi chúng. –

Trả lời

17
  1. Ghi delete kêu gọi các đối tượng quản lý là giống như gọi Vứt bỏ trong C#. Vì vậy, bạn nói đúng, auto_handle cho phép bạn làm những gì bạn sẽ làm với câu lệnh using trong C#. Nó đảm bảo rằng delete được gọi ở cuối phạm vi. Vì vậy, không, bạn không bị rò rỉ bộ nhớ được quản lý nếu bạn không sử dụng auto_handle (bộ thu gom rác sẽ quan tâm đến điều đó), bạn chỉ không gọi Dispose. không cần sử dụng auto_handle nếu các loại giao dịch của bạn không thực hiện IDisposable.

  2. gcroot được sử dụng khi bạn muốn giữ loại được quản lý bên trong lớp gốc. Bạn không thể chỉ khai báo một loại được mang trực tiếp trong một kiểu gốc bằng cách sử dụng biểu tượng mũ ^. Bạn phải dùng gcroot. Đây là một "rác thu thập gốc". Vì vậy, trong khi gcroot (một đối tượng bản địa) sống, bộ thu gom rác không thể thu thập đối tượng này. Khi gcroot bị phá hủy, nó cho phép đi tham chiếu, và bộ thu gom rác là miễn phí để thu thập đối tượng (giả sử nó không có tham chiếu khác). Bạn khai báo một gcroot tự do trong một phương thức như bạn đã làm ở trên - chỉ cần sử dụng cú pháp mũ ^ bất cứ khi nào bạn có thể.

Vì vậy, khi nào bạn sử dụng auto_gcroot?Nó sẽ được sử dụng khi bạn cần phải giữ một loại manged bên trong một lớp bản địa VÀ loại quản lý xảy ra để thực hiện IDisposable. Khi hủy auto_gcroot, nó sẽ thực hiện 2 thứ: gọi delete trên kiểu quản lý (nghĩ về điều này như một cuộc gọi Dispose - không có bộ nhớ nào được giải phóng) và giải phóng tham chiếu (vì vậy loại có thể được thu gom rác).

Hy vọng điều đó sẽ hữu ích!

Một số tài liệu tham khảo:

http://msdn.microsoft.com/en-us/library/aa730837(v=vs.80).aspx

http://msdn.microsoft.com/en-us/library/481fa11f(v=vs.80).aspx

http://www.codeproject.com/Articles/14520/C-CLI-Library-classes-for-interop-scenarios

+1

Cuối cùng, một người có ý nghĩa! –

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