2010-03-22 35 views
37

Tôi đang cố gắng tìm một rò rỉ bộ nhớ bằng cách sử dụng kiến ​​thức bộ nhớ kiến, và tôi đã gặp phải trong một thuật ngữ mới:Đối tượng được ghim là gì?

Đối tượng được ghim.

Một số người có thể cho tôi một giải thích đơn giản về đối tượng này là gì, Làm cách nào tôi có thể ghim/Bỏ đối tượng và phát hiện ai đã ghim đối tượng?

Cảm ơn

Trả lời

44

Đối tượng được ghim là đối tượng không được phép di chuyển. Bộ thu gom rác thường nén bộ nhớ ở chỗ nó di chuyển tất cả các đối tượng sang "một hoặc nhiều cụm". Điều này là để tạo ra khối lớn không gian miễn phí. Điều này về cơ bản có nghĩa là nếu ai đó (bên ngoài) có một con trỏ đến địa chỉ bộ nhớ của một đối tượng, điều này có thể trỏ đến nội dung ngẫu nhiên - khi đối tượng đã di chuyển.

Ghim đối tượng yêu cầu GC không di chuyển CNTT. Điều này thường vô dụng và CHỈ có ý nghĩa khi làm việc với con trỏ - như khi sử dụng PInvoke. Đôi khi bạn cần phải chuyển một địa chỉ vào một cấu trúc (trong thuật ngữ bố trí bộ nhớ), và nếu điều đó được thực hiện trong một lớp, bạn phải ghim nó.

Để trả lời cụ thể:

  • Bạn không thể tìm ra ai gắn một obiect.
  • Ghim được thực hiện với câu lệnh FIXED. Điều này chỉ được phép trong mã không an toàn.

Kiểm tra:

http://msdn.microsoft.com/en-us/library/f58wzh21%28VS.80%29.aspx

+11

Nó không cần phải không an toàn. Như bạn thấy: Buffer = new byte [imageSize]; GCHandle gCBuffer = GCHandle.Alloc (Bộ đệm, GCHandleType.Pinned); – Pedro77

+1

Tuy nhiên, nó đòi hỏi sự tin tưởng đầy đủ, tương đương với mã không an toàn. – usr

18

Một đối tượng ghim là không thể di chuyển xung quanh bằng cách thu gom rác thải, nghĩa là địa chỉ của nó phải được giữ nguyên vì có người khác, thường là một số đoạn mã không được quản lý, phụ thuộc vào đối tượng là tại địa chỉ bộ nhớ xác định.

Thông thường bộ thu gom rác có quyền tự do di chuyển các đối tượng trong bộ nhớ. Trong mã được quản lý, vì trình thu gom rác có khả năng truy cập tất cả các tham chiếu, nó có thể tự do remap một đối tượng đến một vị trí khác và sau đó cập nhật tất cả các tham chiếu đến đối tượng đó để quá trình trong suốt với mã đang chạy. Bằng cách đó, GC có khả năng tổ chức tốt hơn bộ nhớ của chương trình và thu gọn nó nếu cần.

Khi đối tượng không được quản lý tương tác với mã của bạn (trong các phần không an toàn), một tình huống có thể phát sinh khi có một con trỏ ở đâu đó trong một đoạn mã và mã của bạn; mã của bạn đang được xử lý bởi một cuộc gọi COM bên ngoài. Bộ nhớ này không thể được ánh xạ lại vì cuộc gọi COM đang chờ đối tượng ở trong một địa chỉ cụ thể và do đó, nếu nó được di chuyển, GC sẽ không có bất kỳ cách nào để thông báo cho đối tượng COM về thay đổi đó, dẫn đến truy cập vi phạm hoặc tệ hơn.

5

Để ghim đối tượng mà bạn có thể sử dụng fixed keyword:

Tuyên bố cố định ngăn cản việc thu rác từ di dời một biến thể di chuyển . Tuyên bố cố định chỉ được phép trong ngữ cảnh không an toàn .

Ví dụ tôi đã thấy trước đây là chia nhỏ giá trị thành byte để có thể mã hóa thành khóa nối tiếp. Điều này được thực hiện trong một ngữ cảnh unsafe để nhận con trỏ. Các lỗi liên tục bắt đầu xảy ra vì việc thu gom rác sẽ xảy ra giữa quá trình nhận các byte riêng lẻ. Giá trị sẽ được di chuyển và chúng tôi được để lại với một nửa byte đúng, một nửa byte rác.

Giải pháp cho chúng tôi là sử dụng lớp BitConverter. Nếu bạn nhìn vào mã cơ bản của lớp BitConverter, bạn sẽ thấy nó sử dụng từ khóa cố định để ghim mảng byte trong khi lấy các byte từ biến.

4

Một đối tượng được ghim là một trong đó có một vị trí đặt trong bộ nhớ.

Thông thường bộ thu gom rác sẽ thu gọn vùng lưu trữ được quản lý, thay đổi vị trí của các đối tượng trong bộ nhớ. Nếu bạn có một số mã không được quản lý đề cập đến một số đối tượng C# bạn đã tạo, bạn có thể muốn có thể tham chiếu đến vị trí bộ nhớ hoàn toàn. Ghim đối tượng cho phép bạn thực hiện điều này một cách chắc chắn.

Bạn có thể tạo ra chúng bằng cách sử dụng fixed tuyên bố: http://msdn.microsoft.com/en-us/library/f58wzh21%28VS.80%29.aspx

6

đối tượng Pinned được sử dụng khi giao tiếp với mã không được quản lý. Trong mã được quản lý, bộ thu gom rác là miễn phí để di chuyển các khối bộ nhớ xung quanh, vì nó biết về tất cả các tham chiếu đến khối bộ nhớ và có thể cập nhật chúng cho phù hợp.

Khi liên lạc với mã không được quản lý (ví dụ: Win-API) con trỏ tới dữ liệu hoặc bộ đệm thường được chuyển làm đối số. Nếu người thu gom rác được tự do di chuyển dữ liệu đó, các con trỏ sẽ đột nhiên trở nên không hợp lệ. Khi con trỏ được chuyển sang mã không được quản lý, nó không thể cho GC cập nhật con trỏ - hoặc thậm chí biết nơi nó được sử dụng. Để ngăn bộ nhớ di chuyển và đảm bảo rằng dữ liệu vẫn ở vị trí được biết bởi con trỏ của mã không được quản lý, đối tượng có thể được ghim.

6

Lý do bạn có thể ghim đối tượng là nếu bạn đang thực hiện cuộc gọi đến mã không được quản lý.

Khi bộ thu gom rác chạy nó có thể loại bỏ một đối tượng không còn cần thiết nữa. Điều này để lại một "lỗ hổng" của không gian trống trong heap. GC sau đó nén đống bằng cách di chuyển các đối tượng còn lại với nhau để đảm bảo không gian trống nằm trong một khối liên tục (một chút giống như chống phân mảnh đĩa cứng của bạn).

Nó cũng cập nhật tất cả các tham chiếu (trong mã được quản lý) cho bất kỳ đối tượng nào đã được di chuyển như một phần của quá trình nén.

Nếu bạn đang làm việc với mã không được quản lý (ví dụ một số bên ngoài C++) và cho nó một con trỏ đến một đối tượng, không có cách nào để GC nói mã không được quản lý mà đối tượng đã di chuyển sau khi nó đã chạy. Vì vậy, bạn có thể đánh dấu đối tượng mà bạn chia sẻ với mã bên ngoài như được ghim để bạn không gặp vấn đề về con trỏ trở nên không hợp lệ.

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