C # & C ++: «Попытка чтения или записи в защищенную память» Ошибка - PullRequest
2 голосов
/ 29 ноября 2009

Следующий код компилируется без ошибок. По сути, консольное приложение C # 2005 вызывает библиотеку классов VC ++ 2005, которая, в свою очередь, вызывает собственный код VC ++ 6. Я получаю следующую ошибку при запуске приложения C # 2005:

" Необработанное исключение: System.AccessViolationException: попытка чтения или записи защищенной памяти. Это часто указывает на то, что другая память повреждена. "

В чем причина этой ошибки? И как это исправить?

Edit1: сбой на линии StdStringWrapper ssw = w.GetNext () ;

Edit2: Я последовал совету Навина и использовал целочисленный индекс вместо итераторов, и ошибок больше нет. Большое спасибо всем, кто прокомментировал!

Код, написанный на C # 2005 как консольное приложение:

class Program
{
    static void Main(string[] args)
    {
        Class1 test= new Class1();
        test.PerformAction();
        test.PerformAction();
        test.PerformAction();
        test.PerformAction();
    }
}

Код, написанный на VC ++ 2005 в виде библиотеки классов:

public ref class Class1
{
    public:
        void PerformAction();       
};

void Class1::PerformAction()
{
    DoSomethingClass d;
    StdStringContainer w;
    d.PerformAction(w);

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

Код, написанный на VC ++ 6 в виде библиотеки динамических ссылок:

#ifdef NATIVECODE_EXPORTS
    #define NATIVECODE_API __declspec(dllexport)
#else
    #define NATIVECODE_API __declspec(dllimport)
#endif

class NATIVECODE_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();
}

//

class NATIVECODE_API StdStringContainer
{
    private:
        std::vector<StdStringWrapper> _items;
        std::vector<StdStringWrapper>::iterator _it;

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

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

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

StdStringWrapper& StdStringContainer::GetNext()
{
    std::vector<StdStringWrapper>::iterator it = _it;
    _it++;

    return *it;
}

//

class NATIVECODE_API DoSomethingClass
{
    public:
        void PerformAction(StdStringContainer &s);
};

void DoSomethingClass::PerformAction(StdStringContainer &s)
{
    StdStringWrapper w1;
    w1.Append("This is string one");
    s.Add(w1);

    StdStringWrapper w2;
    w2.Append("This is string two");
    s.Add(w2);
}

Ответы [ 4 ]

1 голос
/ 29 ноября 2009

Элемент _it в StdStringContainer никогда не инициализируется, чтобы указывать на вектор _items. Это означает, что это недопустимый итератор. Когда вы присваиваете _it it в GetNext(), вы присваиваете it недопустимое неинициализированное значение, существовавшее в _it. Затем вы увеличиваете неинициализированный _it через _it++, что и вызывает вашу ошибку.

Как говорит Страуструп в 19.2, неинициализированный итератор является недействительным итератором. Это означает, что ваш неинициализированный _it недействителен, а операции, выполняемые с ним, не определены и могут привести к серьезному сбою.

Однако ваша проблема глубже. Время жизни итераторов существенно отличается от перечисляемых ими контейнеров. На самом деле не существует «хороших» способов сделать то, что вы пытаетесь сделать, с помощью одного члена итератора, такого как этот, если контейнер не является неизменным и инициализируется в конструкторе.

Если вы не можете раскрыть имена пространства имен std :: name, рассматривали ли вы их псевдонимы с помощью typedef, например? Что из вашей организации или проекта делает невозможным выставление шаблонов классов?

0 голосов
/ 29 ноября 2009

Основная проблема, с моей точки зрения, заключается в том, что вы сохраняете iterator в vector в вашем stdStringContainer классе. Помните, что всякий раз, когда вектор изменяет размеры, все существующие итераторы становятся недействительными. Таким образом, всякий раз, когда вы выполняете операцию вставки в вектор, возможно, что он изменяет размеры и ваш существующий итератор становится недействительным. Если вы попытаетесь разыменовать его в GetNext(), он получит доступ к неверной ячейке памяти. Чтобы проверить, действительно ли это так, попробуйте зарезервировать начальный размер вектора до некоторого относительно большого числа, чтобы изменение размера не происходило. Вы можете зарезервировать размер, используя метод reserve(), в этом случае гарантируется, что capacity() вектора больше или равно зарезервированному значению.

0 голосов
/ 29 ноября 2009

Я предполагаю, что у вас происходит сбой, потому что std::string и std::vector в интерфейсе между двумя модулями C ++ были скомпилированы с разными компиляторами и библиотеками времени выполнения.

Возможно изменение схемы памяти вектора и строки в период между VC6 и 2005.

Когда библиотека DLL 2005 года выделяет объекты типа StdStringContainer и StdStringWrapper, она делает это на основе объявлений string и vector в заголовках 2005 года.

Когда функции-члены вызываются для этих объектов (которые были скомпилированы с помощью компилятора и библиотек VC6), они принимают другую структуру памяти и терпят неудачу с нарушениями доступа.

0 голосов
/ 29 ноября 2009

Похоже, у вас утечка памяти. Я бы посоветовал искать в любом месте, где есть арифметика указателей, запись в память или использование массива. Проверьте условия границ в доступе к массиву.

Еще одна проблема: утечка многих даже не будет в вашем коде. В этом случае вам придется исключить библиотеку из вашего проекта.

...