تسرب الذاكرة عند استدعاء رمز غير مدار من التعليمات البرمجية المدارة في نظام التشغيل Windows 7

StackOverflow https://stackoverflow.com/questions/1505489

سؤال

عندما أسمي رمز C ++ غير المدار عن كود C #، يبدو لي أن لديك نوع من تسرب الذاكرة.
يقرأ C ++ البيانات من ملف باستخدام ifstream.Read، ويكتبه إلى متجه.

يحدث هذا فقط بعد الترقية إلى نظام التشغيل Windows 7، لا يحدث في نظام التشغيل Vista، ولكن إذا كنت أستخدم إصدار من DLL الأصلي الذي تم تجميعه على نظام التشغيل Vista، فإنه لا يغير أي شيء!
إذا قمت بتشغيل نفس الرمز C ++ مباشرة، دون الإخلال المدار، لا يوجد تسرب الذاكرة!
إذا قمت بتشغيل العملية المدارة، ولكن ضمن عملية VSHOST، لا يوجد تسرب الذاكرة!

إليك توقيع الدعوة:

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

والأواني الأصلية:

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

عندما أسميها من C ++، أسميها مثل هذا:

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

عندما أنظر إلى عدادات الأداء للذاكرة المدارة وغير المدارة، أرى أن جميع الذاكرة تأتي من التعليمات البرمجية غير المدارة.
بالنظر إلى أن التنظيم بسيط جدا، لا أفهم لماذا هناك فرق بين استدعاء C ++ مباشرة أو من خلال C #.
أنا أيضا لا أعرف لماذا يحدث هذا فقط على نظام التشغيل Windows 7 (كان على كلا تثبيت Windows .NET 3.5 SP1).

هل لدى أي شخص فكرة ما هو سبب هذا؟

أيضا إذا كان أي شخص يعرف أداة تنموبي الذاكرة الأصلية تعمل على النافذة 7، سأكون سعيدا لمعرفة (الآن قمت بطباعة فقط إلى وحدة تحكم جميع تخصيص الذاكرة الصريح ولا توجد فروق).

هل كانت مفيدة؟

المحلول

أنا متأكد من أن المشكلة مرتبطة بنشاف أنواع البيانات C # إلى أجزاء مكافحة C ++ الخاصة بهم. نظرا لأنك تنكش قيم العودة إلى قيمة 1 بايت موقعة، فربما يجب عليك القيام بنفس الشيء في وسيطات الوظيفة؟ نوع BOOL C # هو 4 بايت، ربما تسريب هناك؟

أيضا، قد تساعد تحديد النوع غير المدمن على السلاسل.

[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);

شرح للمعلق:

لنوع BOOL C ++:

بشكل عام، يتم تحويل قيمة صفر أو مؤشر فارغة إلى FALSE، يتم تحويل أي قيمة أخرى إلى True.

...

تحدد المكتبة القياسية لعام 1998 C ++ تخصصا من قالب ناقلات BOOL. يشير وصف الفصل إلى أن التنفيذ يجب أن يحزم العناصر بحيث يستخدم كل BOOL فقط قليلا من الذاكرة.

لذلك، مهما كانت القيمة التي تستخدمها، ستحصل على Voolean C ++ ذات القيمة الحقيقية أو FALSE.

نصائح أخرى

لسوء الحظ بمجرد أن تنطوي على سلاسل، لا يوجد حشد بسيط.

سنحتاج إلى مزيد من البيانات من أجل مساعدتك في تعقب هذه المشكلة. هل يمكنك تقديم ما يلي

  • توقيع الطريقة الأصلية
  • كيف يتم إدارة ذاكرة السلاسل في الكود الأصلي؟
  • ربما عينة C ++ حيث تستخدم API؟

تعديل

جرب التوقيع التالي. يخبر هذا CLR عدم وجود ذاكرة Marshal في كلا الاتجاهين ولكن بدلا من ذلك تجاوز البيانات.

    [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);

لقد وجدت استخدام clr profiler. مفيدة عند العثور على تسرب الذاكرة الخاصة بي.

هل أنت متأكد من وجود تسرب الذاكرة؟

ما هو أساسك لتحديد تسرب الذاكرة. أنت تقول أنه يمكنك رؤيته من عدادات الأداء، لكن ماذا تلاحظ فعلا؟ هل ترى منحنى مرتفع للغاية أو واحد يستقر على مستوى عال؟ غالبا ما يتم الخلط بين استهلاك الذاكرة في الغالب على تسرب الذاكرة.

بالمناسبة. هل يمكنك نشر تعريف وظيفة C ++ كذلك؟

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top