التحدي خطأ وقت التشغيل عند استدعاء التعليمات البرمجية الأصلية من التعليمات البرمجية المدارة

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

سؤال

First_Layer

لدي win32 dll في VC++6 service pack 6.دعونا نسمي هذا dll كما FirstLayer.أنا لم يكن لديك الوصول إلى FirstLayer شفرة المصدر ولكن أريد أن نسميها تمكنت من التعليمات البرمجية.المشكلة هي أن FirstLayer يجعل الاستخدام المكثف من الأمراض المنقولة جنسيا::ناقلات std::string وليس هناك طريقة تنظيم هذه الأنواع في C# التطبيق مباشرة.رمز لهذا طبقة أدناه يوضح مثال على ما يمكن العثور عليها في هذا dll.

Second_Layer

الحل الذي يمكن أن نفكر من هو أول خلق آخر win32 dll في VC++6 service pack 6.دعونا نسمي هذا dll مثل "SecondLayer".SecondLayer بمثابة التفاف على FirstLayer الأساس الذي يحول المحكمة أنواع مخصصة مكتوب غير المحكمة الدرجة أنواع.

Third_Layer

أنا خلقت أيضا VC++2005 مكتبة فئة مجمع على SecondLayer.هذا المجمع يقوم بكل الأعمال القذرة من تحويل غير المدارة SecondLayer في التعليمات البرمجية المدارة.دعونا نسمي هذه الطبقة باسم "ThirdLayer".رمز هذه الطبقة كما هو موضح أدناه هو مبسط لبيان خطأ لذلك لا تفعل المذكورة أعلاه التحويل.

Fourth_Layer

على رأس كل شيء ، أنا خلقت C#2005 تطبيق وحدة التحكم للاتصال ThirdLayer.دعونا نسمي هذا C# "تطبيق وحدة تحكم" كما "FourthLayer".

دعوة تسلسل ملخص

FourthLayer(C#2005) -> ThirdLayer(VC++2005) -> SecondLayer(VC++6) -> FirstLayer(VC++6)

خطأ وقت التشغيل

رمز أدناه ترجمة/بناء بدون أخطاء ولكن أنا على خطأ وقت التشغيل التالية:

حدث استثناء غير معالج:النظام.AccessViolationException:حاول قراءة أو كتابة الذاكرة المحمية.هذا هو في كثير من الأحيان إشارة إلى أن الذاكرة الأخرى تالفة.في SecondLayer.PassDataBackToCaller(SecondLayer ,StdVectorWrapper* ) في العينة.ThirdLayer.PassDataBackToCaller() في c:\project\on المشاريع الجارية est\sample hirdlayer hirdlayer.cpp:خط 22 في FourthLayer.البرنامج.Main(String[] args) في C:\Project\On المشاريع الجارية est\Sample\FourthLayer\Program.cs:خط 14*

هذا الخطأ لا يلزم تظهر عندما FourthLayer تطبيق يتم تنفيذها على نظام تشغيل مختلف.على سبيل المثال, Windows XP, لا يوجد خطأ ولكن نظام التشغيل الأخرى مثل ويندوز فيستا و ويندوز 7 ، خطأ سوف تظهر.

أنا لا أفهم ما هو سبب هذا.أي أفكار ؟ كيف يمكن أن تذهب حول تعديل التعليمات البرمجية لتصحيح هذا ؟

// Fourth_Layer (C#2005 تطبيق وحدة التحكم)

class FourthLayer
{
    static void Main(string[] args)
    {
        ThirdLayer thirdLayer = new ThirdLayer();
        thirdLayer.PassDataBackToCaller();
    }
}

// Third_Layer (VC++2005 مكتبة الفئة)

public ref class ThirdLayer
{
    private:
        SecondLayer *_secondLayer;

    public:
        ThirdLayer();
        ~ThirdLayer();
        void PassDataBackToCaller();
};

ThirdLayer::ThirdLayer()
{
    _secondLayer = new SecondLayer();
}

ThirdLayer::~ThirdLayer()
{
    delete _secondLayer;
}

void ThirdLayer::PassDataBackToCaller()
{ 
    StdVectorWrapper v;
    _secondLayer->PassDataBackToCaller(v);

    for (int i=0; i<v.GetSize(); i++)
    {
        StdStringWrapper s = v.GetNext();
        std::cout << s.CStr() << std::endl;
    }
}

// Second_Layer الرئيسي الدرجة (VC++6 win32 dll)

class SECOND_LAYER_API SecondLayer
{
    private:
        FirstLayer *_firstLayer;

    public:
        SecondLayer();
        ~SecondLayer();
        void PassDataBackToCaller(StdVectorWrapper &toCaller);

    private:
        void ConvertToStdVectorWrapper(
            const std::vector<std::string> &in, StdVectorWrapper &out);
};

SecondLayer::SecondLayer() : _firstLayer(new FirstLayer())
{
}

SecondLayer::~SecondLayer()
{
    delete _firstLayer;
}

void SecondLayer::PassDataBackToCaller(StdVectorWrapper &toCaller)
{ 
    std::vector<std::string> v;
    _firstLayer->PassDataBackToCaller(v);
    ConvertToStdVectorWrapper(v, toCaller);
}

void SecondLayer::ConvertToStdVectorWrapper(
    const std::vector<std::string> &in, StdVectorWrapper &out)
{
    for (std::vector<std::string>::const_iterator it=in.begin(); it!=in.end(); ++it)
    {
        StdStringWrapper s((*it).c_str());
        out.Add(s);
    }
}

// Second_Layer - StdVectorWrapper فئة (VC++6 win32 dll)

class SECOND_LAYER_API StdVectorWrapper
{
    private:
        std::vector<StdStringWrapper> _items;
        int index;  

    public: 
        StdVectorWrapper();
        void Add(const StdStringWrapper& item);
        int GetSize() const;  
        StdStringWrapper& GetNext(); 
};

StdVectorWrapper::StdVectorWrapper()
{
    index = 0;
}

void StdVectorWrapper::Add(const StdStringWrapper &item)
{
    _items.insert(_items.end(),item);
}

int StdVectorWrapper::GetSize() const
{
    return _items.size();
}

StdStringWrapper& StdVectorWrapper::GetNext()
{
    return _items[index++];
}

// Second_Layer - StdStringWrapper فئة (VC++6 win32 dll)

class SECOND_LAYER_API StdStringWrapper
{
    private:
        std::string _s;

    public:  
        StdStringWrapper();
        StdStringWrapper(const char *s);
        void Append(const char *s);
        const char* CStr() const;  
};

StdStringWrapper::StdStringWrapper()
{
}

StdStringWrapper::StdStringWrapper(const char *s)
{
    _s.append(s);
}

void StdStringWrapper::Append(const char *s)
{
    _s.append(s);
}

const char* StdStringWrapper::CStr() const
{
    return _s.c_str();
}

// First_Layer (VC++6 win32 dll)

class FIRST_LAYER_API FirstLayer
{
    public:
        void PassDataBackToCaller(std::vector<std::string> &toCaller);
};

void FirstLayer::PassDataBackToCaller(std::vector<std::string> &toCaller)
{
    std::string a, b;
    a.append("Test string 1"); 
    b.append("Test string 2");
    toCaller.insert(toCaller.begin(),a);
    toCaller.insert(toCaller.begin(),b);
}
هل كانت مفيدة؟

المحلول

لقد وجدت الحل.Bascially, هناك نوعان من المشاكل معها.

مشكلة واحدة (بين FirstLayer و SecondLayer)

بشكل افتراضي ، يتم الإعداد التالية VC++6 مؤشرات.هذا الإعداد يجب أن يكون تغيير مؤشرات Dll لكل من FirstLayer و SecondLayer.وكلاهما يجب إعادة تجميعها مع هذا الإعداد الجديد من أجل أن تعمل.

المشروع->إعدادات->التبويب C/C++->الفئة:رمز جيل->استخدام مكتبة وقت التشغيل->مؤشرات Dll

المشكلة الثانية (بين SecondLayer و ThirdLayer)

على StdStringWrapper و StdVectorWrapper الدرجة التي كتبت لا تنفذ نسخة عميق.لذلك كل ما عليك القيام به هو إضافة التالي إلى StdStringWrapper و StdVectorWrapper الدرجة لتنفيذ نسخة عميق.

  • منشئ نسخة
  • عامل التعيين
  • ديكونستروكتور

تحرير: حل بديل المشكلة اثنين

أفضل حل هو استخدام clone_ptr لجميع العناصر الواردة في std::ناقلات فضلا عن الأمراض المنقولة جنسيا::ناقلات نفسها.هذا يلغي الحاجة إلى منشئ نسخة التنازل مشغل ديكونستروكتور.حتى داخل StdVectorWrapper الدرجة ، أن تعلن أنها

clone_ptr< std::vector< clone_ptr< StdStringWrapper > > > _items;

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