2009-10-01 34 views
7

Khi tôi gọi một mã C++ không được quản lý từ mã C# của tôi, tôi dường như có một số loại rò rỉ bộ nhớ.
C++ đọc dữ liệu từ một tệp bằng cách sử dụng ifstream.read và ghi nó vào Vector.rò rỉ bộ nhớ khi gọi mã không được quản lý từ mã được quản lý trong Windows 7

Điều này xảy ra chỉ sau khi nâng cấp lên Windows 7, không xảy ra trên Vista, nhưng nếu tôi sử dụng phiên bản dll gốc được biên dịch trên Vista, nó không thay đổi gì cả!
Nếu tôi chạy cùng một mã C++ trực tiếp, không có tương tác được quản lý, không có rò rỉ bộ nhớ!
Nếu tôi chạy quy trình được quản lý, nhưng trong quá trình vshost, không có rò rỉ bộ nhớ!

Dưới đây là chữ ký cuộc gọi:

 [DllImport(DllPath, CharSet = CharSet.Unicode)] 
    [return: MarshalAs(UnmanagedType.I1)] 
    public static extern bool MyMethod(
     int x, 
     string y, 
     string z, 
     bool v, 
     bool w); 

và mẹ đẻ một:

MyDll_Export bool APIENTRY MyMethod(
int x, 
const wchar_t* y, 
const wchar_t* z, 
bool v, 
bool w) 

Khi tôi gọi nó từ C++, tôi gọi nó là như thế này:

MyMethod(1, L"My String 1", L"My String 2", true, true) 

Khi tôi nhìn vào các bộ đếm hiệu suất cho bộ nhớ được quản lý và không được quản lý, tôi thấy rằng tất cả bộ nhớ đến từ mã không được quản lý.
Xét rằng marshaling khá đơn giản, tôi không hiểu tại sao có sự khác biệt giữa việc gọi C++ trực tiếp hoặc thông qua C#.
Tôi cũng không biết tại sao điều này chỉ xảy ra trên Windows 7 (cả hai bản cài đặt Windows đều có .net 3.5 SP1).

Có ai có ý tưởng lý do cho việc này không?

Ngoài ra nếu có ai biết về công cụ định dạng bộ nhớ gốc hoạt động trên Cửa sổ 7, tôi rất vui được biết (hiện tại tôi đã in để bàn giao tất cả cấp phát bộ nhớ rõ ràng và không có sự khác biệt).

+0

LeakDiag [http://mcfunley.com/277/using-leakdiag-to-debug-unmanaged-memory-leaks] hoặc AQTime của AutomatedQA có thể thực hiện phân tích rò rỉ không được quản lý. –

+0

Bạn sử dụng bộ đếm hiệu năng nào để đo mức tiêu thụ bộ nhớ? –

+0

Bạn đã gắn thẻ câu hỏi "vshost.exe". Ứng dụng có chạy dưới Visual Studio khi bạn đo mức tiêu thụ bộ nhớ không? –

Trả lời

5

Tôi chắc chắn vấn đề liên quan đến việc sửa đổi các kiểu dữ liệu C# thành các bộ đếm C++ của chúng. Vì bạn đang marshaling giá trị trả về bool thành một giá trị byte đã ký 1, có lẽ bạn nên làm tương tự với các đối số hàm? Kiểu bool C# là 4 byte, có thể bạn đang bị rò rỉ ở đó?

Ngoài ra, việc chỉ định loại không được quản lý cho các chuỗi có thể hữu ích.

[DllImport(DllPath, CharSet = CharSet.Unicode)] 
[return: MarshalAs(UnmanagedType.I1)] 
public static extern bool MyMethod(
     int x, 
     [MarshalAs(UnmanagedType.LPWStr)] 
     [In] string y, 
     [MarshalAs(UnmanagedType.LPWStr)] 
     [In] string z, 
     [MarshalAs(UnmanagedType.I1)] 
     bool v, 
     [MarshalAs(UnmanagedType.I1)] 
     bool w); 

Giải thích cho commentor:

For the C++ bool type:

Nói chung, một số không hoặc con trỏ null-giá trị được chuyển thành sai, giá trị bất kỳ khác được chuyển thành sự thật.

...

Các Thư viện chuẩn C++ 1998 định nghĩa một chuyên môn hóa của vector mẫu cho bool. Mô tả của lớp học chỉ ra rằng việc triển khai phải đóng gói các yếu tố để mỗi bool chỉ sử dụng một bit bộ nhớ.

Vì vậy, khá nhiều giá trị bạn sử dụng, bạn sẽ nhận được giá trị boolean c + + với giá trị đúng hoặc sai.

+0

Nếu bool không khớp với kích thước, nó sẽ không bị rò rỉ bộ nhớ. , hoặc một số loại tham nhũng ngăn xếp. – user7116

+0

scott tệp đẹp, C# marshals bools dưới dạng 4bytes. Thuộc tính marshalas bị thiếu cho v và w. http://blogs.msdn.com/oldnewthing/archive/2009/08/13/9867383.aspx –

+0

err. có nghĩa là 'find' –

2

Thật không may một khi bạn liên quan đến chuỗi, không có bản sửa lỗi nào đơn giản.

Chúng tôi sẽ cần thêm một số dữ liệu để giúp bạn theo dõi vấn đề này. bạn có thể cung cấp sau đây

  • Native Method Chữ ký
  • Làm thế nào là bộ nhớ cho các dây được quản lý trong mã nguồn gốc?
  • Có lẽ mẫu C++ nơi bạn sử dụng API?

EDIT

Hãy thử chữ ký sau. Điều này cho CLR không để marshal bộ nhớ trong cả hai chiều mà thay vào đó chỉ vượt qua các dữ liệu trong

[DllImport(DllPath, CharSet = CharSet.Unicode)] 
    [return: MarshalAs(UnmanagedType.I1)] 
    public static extern bool MyMethod(
      int x, 
      [In] string y, 
      [In] string z, 
      bool v, 
      bool w); 
+0

cảm ơn, câu hỏi được cập nhật, chuỗi được truyền là hằng số. –

+0

[In] không giúp được gì, tại sao nó lại thay đổi giữa Vista và Windows 7? cũng vậy, tôi không đề cập đến việc tôi gọi phương thức này chỉ một lần. –

1

. Tôi thấy việc sử dụng các CLR Profiler hữu ích khi tìm rò rỉ bộ nhớ của tôi.

0

Bạn có chắc chắn rằng có rò rỉ bộ nhớ không?

Cơ sở của bạn để xác định rò rỉ bộ nhớ là gì. Bạn nói rằng bạn có thể thấy nó từ các quầy hiệu suất, nhưng bạn thực sự quan sát điều gì?Bạn có nhìn thấy một đường cong tăng lên đáng kể, hay một đường cong lắng xuống ở mức cao? Mức tiêu thụ bộ nhớ cao thường bị nhầm lẫn do rò rỉ bộ nhớ.

btw. Bạn có thể gửi cho bạn định nghĩa hàm C++ không?

+0

Tôi thấy đường cong tăng liên tục. Tôi đã đăng định nghĩa hàm C++, nếu bạn ngụ ý phần thân, thì nó chỉ đọc dữ liệu từ một tệp bằng ifstream.read –

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