2012-01-26 53 views
7

Tôi viết một mô-đun trong C# để xuất một số chức năng được sử dụng trong C. Tôi cần cấp phát một số bộ nhớ cho một số cấu trúc được truyền giữa C < -> C#.Bất kỳ sự khác biệt nào giữa malloc và Marshal.AllocHGlobal?

Những gì tôi phân bổ trong C Tôi làm với malloc, và trong C# tôi làm với Marshal.AllocHGlobal() (để cấp phát bộ nhớ không được quản lý được chuyển cho C).

Có vấn đề gì nếu tôi giải phóng() bộ nhớ được cấp phát bằng Marshal.AllocHGlobal và nếu tôi giải phóng bộ nhớ bằng Marshal.FreeHGlobal() được cấp phát bằng malloc?

Cảm ơn

+0

Cảm ơn mọi câu trả lời – bzamfir

+0

Cảm ơn. Trên thực tế những gì tôi đã làm là tạo ra trong các chức năng xuất khẩu lib của tôi AllocateMem, và FreeMem, mà tôi đề nghị được sử dụng bằng cách gọi chương trình, khi tạo cấu trúc được chuyển đến lib. Nhưng tôi đã tự hỏi của một người không tuân thủ quy tắc này và chuyển đến lib của tôi một số cấu trúc phân bổ với malloc (hoặc bất cứ điều gì khác), những gì sẽ xảy ra? – bzamfir

+0

Vấn đề là các cấu trúc có một số con trỏ đến char (cho chuỗi) mà tôi phải phân bổ và chuyển đến mã gọi. Và nếu mã gọi điện thoại cố gắng giải phóng bộ nhớ đó bằng miễn phí() thì sao? Đó là lý do tại sao tôi tạo FreeMem, mà tôi đã thực hiện với FreeHGlobal, được sử dụng để giải phóng bộ nhớ khi gọi prog. Nếu không thì đó là trách nhiệm của lập trình viên gọi mã. – bzamfir

Trả lời

15

Quy tắc vàng là bạn phải deallocate từ cùng một đống được sử dụng để cấp phát bộ nhớ.

Nếu bạn phân bổ nó với malloc(), bạn phải deallocate nó với free() từ cùng một C RTL. Và tương tự ở bên được quản lý, AllocHGlobal() phải được cân bằng bởi FreeHGlobal().

Hiện tại, AllocHGlobal() được triển khai bằng cách gọi hàm Win32 LocalAlloc. Vì vậy, bạn có thể giải phóng bộ nhớ như vậy với một cuộc gọi đến LocalFree ở phía gốc. Và ngược lại.

Nếu bạn muốn sử dụng một đống được chia sẻ giữa nguồn gốc và được quản lý, thông thường sử dụng vùng heap COM. Ở phía gốc, hãy sử dụng CoTaskMemAlloc()CoTaskMemFree(). Về việc sử dụng bên được quản lý Marshal.AllocCoTaskMem()Marshal.FreeCoTaskMem().

Tuy nhiên, bạn nên tránh thiết kế hệ thống như thế này. Nó là đơn giản hơn nhiều để dính vào một quy tắc rằng tất cả bộ nhớ được phân bổ ở phía quản lý được deallocated ở đó, và tương tự như vậy cho bên bản địa. Nếu bạn không tuân thủ quy tắc đó, bạn sẽ sớm mất dấu người chịu trách nhiệm về điều gì.

4

Có thể có hoặc không có vấn đề gì - điều này hoàn toàn phụ thuộc vào việc triển khai thực hiện. Không bao giờ dựa vào chi tiết triển khai cho chức năng ứng dụng của bạn!

Vì vậy, tôi khuyên bạn nên không sử dụng Marshal.AllocHGlobal(), malloc(), Marshal.FreeHGlobal()free() ngang.

Một ví dụ, nơi bạn sẽ gặp rắc rối nghiêm trọng là nếu bạn sử dụng thư viện, một số loại phép thuật lạ mắt malloc()/free() - thậm chí bạn có thể không biết điều đó.

+1

Không, nó chỉ đơn giản là không làm việc ở tất cả! Không có hoặc có thể không về nó! –

+0

@DavidHeffernan Thú vị! Chúng tôi đã có điều này trong một ứng dụng và nó thường làm việc OK trong Mono, mọi thứ bắt đầu phá vỡ với các thư viện ưa thích, vì vậy chúng tôi điều tra. –

+1

Nghe có vẻ như nó không thực sự hoạt động. Nhưng Mono có thể là quái thú khác. Tôi giả định MS.và do đó tính tổng hợp của bình luận của tôi. –

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