Использование класса C++ в форме Windows приводит к System.AccessViolationException

Я написал несколько классов C++, в которых используются различные библиотеки C++. Я создал проект Windows Form и настроил его для успешного использования моих классов. Однако недавно я создал еще один класс С++, и теперь я постоянно получаю:

A first chance exception of type 'System.AccessViolationException' occurred in TEST_OCU.exe

что приводит к:

 An unhandled exception of type 'System.TypeInitializationException' occurred in Unknown Module.
 Additional information: The type initializer for '<Module>' threw an exception.

Программа еще даже не запущена, а новый проблемный класс C++ еще даже не создан. Если я закомментирую вызов new и у меня будет только указатель на этот новый класс C++, все будет отлично компилироваться. НО, если где-то я делаю что-то вроде:

 if(new_class_ptr != NULL)
    new_class_ptr->SomeFunction()  //It doesn't matter what function this is

Это вызовет эти нарушения снова


Некоторые факты:

  • Компиляция и компоновка в порядке, похоже, это проблема времени выполнения.
  • В моем решении используются неуправляемые библиотеки и классы C++ (которые я написал) и одна управляемая форма C++.
  • До сих пор у меня не было никаких проблем, я некоторое время успешно использовал несколько библиотек C++. Это вызвано новым классом C++, который я недавно написал.
  • Класс C++, который вызывает эти нарушения, использует std::ifstream для чтения в файле. Если я закомментирую std::ifstream input_file(filename);, мой проект Forms запустится успешно.
  • Если я использую класс C++ в простом проекте Win32, он прекрасно компилируется и работает с std::ifstream.
  • У меня есть сильное ощущение, что это связано с этим вопросом

Может ли кто-нибудь дать какой-либо совет? Спасибо


EDIT: я предоставляю некоторые части кода моей формы, которые у меня есть. RTSPConnection работает нормально, класс-нарушитель — RTPStream.

public ref class Form1 : public System::Windows::Forms::Form
{
public:
  // ... Lots of generated code here ...

//Calls I've written
    private: static RTSPConnection * rtsp_connection_ = NULL; //This class works
    private: static RTPStream * rtp_connection_ = NULL; //This class does not
    bool streaming_;
    System::Threading::Thread^ streaming_thread_;

    private: System::Void Form1_Load(System::Object^  sender, System::EventArgs^  e) {
        if(rtsp_connection_ == NULL)
        {
            rtsp_connection_ = new RTSPConnection("rtsp://192.168.40.131:8554/smpte");
            streaming_ = false;
        }

            //if(rtp_connection_ == NULL)
            //   rtp_connection_ = new RTPStream("test");

    }

    private: System::Void Form1_FormClosing(System::Object^  sender, System::Windows::Forms::FormClosingEventArgs^  e) {
        if(rtsp_connection_ != NULL)
            rtsp_connection_->StopStreaming();
    }

    private: System::Void button1_MouseClick(System::Object^  sender, System::Windows::Forms::MouseEventArgs^  e) {
        if(!streaming_)
        {
            //Start Streaming
            streaming_thread_ = gcnew Thread(gcnew ThreadStart(&Form1::WorkerThreadFunc));
            streaming_thread_->Start();

            this->button1->Text = L"Stop Streaming";
            streaming_ = true;
        }
        else
        {
            //Stop Streaming
            if(rtsp_connection_ != NULL)
            rtsp_connection_->StopStreaming();

            //THIS CALL RIGHT HERE WILL THROW AN ACCESS VIOLATION
            if(rtp_connection_ != NULL)
                rtp_connection_->StopStreaming();
            this->button1->Text = L"Start Streaming";
             streaming_ = false;
        }
    }
 };

person Constantin    schedule 05.07.2012    source источник
comment
Вам нужно будет отладить его. Project + Properties, вкладка «Отладка», установите флажок «Включить отладку неуправляемого кода». Debug + Exceptions, установите флажок Thrown для исключений Win32.   -  person Hans Passant    schedule 05.07.2012
comment
Не могу найти это, я на VS2010.   -  person Constantin    schedule 05.07.2012
comment
stackoverflow.com/questions/11091356/   -  person Hans Passant    schedule 05.07.2012
comment
Ганс, у меня нет похожей страницы свойств. В моем проекте Windows Forms C++ используется тот же макет страницы свойств C++, что и в моем проекте Win32 C++. Я хотел бы упомянуть, что у меня есть исключения C++ Exception и Win 32 Exceptions в Debug-›Exceptions.   -  person Constantin    schedule 05.07.2012
comment
Установите тип отладчика «Смешанный».   -  person Hans Passant    schedule 05.07.2012
comment
Готово, что я ищу сейчас? Первым выброшенным исключением было нарушение прав доступа. Самый высокий уровень, относящийся к моей программе: TEST_OCU.exe!<CrtImplementationDetails>::LanguageSupport::Initialize() Line 698 C++   -  person Constantin    schedule 05.07.2012
comment
AccessViolationException, вероятно, означает, что вы пытаетесь разыменовать NULL или неинициализированный указатель где-то в вашем коде C++.   -  person millimoose    schedule 05.07.2012
comment
Я бы согласился, но точка останова никогда не достигается, кажется, это происходит еще до того, как программа даже вошла в main и загружаются все классы.   -  person Constantin    schedule 05.07.2012
comment
Все зависит от этой строки: std::ifstream input_file(filename);, где filename — это std::string. Несмотря на то, что эта строка никогда не достигается во время выполнения, закомментирование этой строки или изменение ее на std::ifstream input_file(); устраняет нарушения. std::ifstream input_file; не работает.   -  person Constantin    schedule 05.07.2012
comment
Вы получаете почти ту же ошибку в C#, если у вас есть статические члены класса, которые зависят друг от друга, и они не инициализируются в том порядке, в котором вы ожидаете. В C++, если у вас есть статический синглтон и другой статический член, ссылающийся на него, вы получите эту ошибку при инициализации модуля, если член был инициализирован до синглтона. Есть ли в вашем классе или исходном файле какие-либо статические данные?   -  person arx    schedule 05.07.2012
comment
Аркс, это так... Позвольте мне разобраться в этом глубже. (Забавно, я сначала тоже так подумал, но списал это, когда закомментировал конструктор std::ifstream, и он сработал.) Я хотел бы добавить, я написал обходной путь с использованием FILE и fread... но я бы предпочел используйте потоки С++ для чтения моих файлов...   -  person Constantin    schedule 05.07.2012
comment
Form1 имеет статические члены, но, похоже, не выполняет никакой статической инициализации, что и вызывает проблему. Выполняет ли RTPStream статическую инициализацию?   -  person arx    schedule 05.07.2012
comment
Статическая инициализация выполняется с помощью if(rtsp_connection_ == NULL). В неуправляемом С++ это было бы нормально... разве это не работает в управляемом? Если я не запутался в том, что означает статическая инициализация. Я намеренно оставил указатель RTPStream равным NULL, чтобы показать, что мне не нужно создавать экземпляр класса RTPStream, чтобы вызвать AccessViolation (обратите внимание, что я ВСЕГДА проверяю, имеют ли указатели значение NULL перед их использованием).   -  person Constantin    schedule 05.07.2012
comment
Microsoft C++/CLI != стандартный C++. Но это, безусловно, выглядит нормально: static RTPStream *rtp_connection_ = NULL. В: вы уверены, что в RTPStream нет статических классов, которые не являются указателями (т. е. которые могут быть непреднамеренно созданы при запуске программы)?   -  person paulsm4    schedule 05.07.2012
comment
Только что проверил, только POD, указатели и std::string. Я хотел бы отметить, что моя программа работает отлично, используя подход FILE *fp и fread вместо std::ifstream. (Я не согласен с этим, я бы хотел, чтобы это было на С++). Также большое спасибо за то, что вы так отзывчивы до сих пор.   -  person Constantin    schedule 05.07.2012
comment
Под статической инициализацией я подразумевал инициализацию статического члена чем-то более сложным, чем NULL (например, экземпляром класса). И вы не делаете этого в Form1, но может быть в RTPStream?   -  person arx    schedule 06.07.2012


Ответы (1)


Эти два утверждения кажутся противоречащими друг другу:

Программа еще даже не запущена, а новый проблемный класс C++ еще даже не создан.

Если я закомментирую новый вызов и у меня будет только указатель на этот новый класс C++, все будет отлично компилироваться.

В: Не могли бы вы опубликовать код, где вы называете «новым»? Или вы называете «новым» — возможно, вы просто имели в виду «если я закомментирую свой новый класс»?

В: Не могли бы вы установить точку останова в своем конструкторе, просмотреть трассировку стека и посмотреть, кто ее вызывает? И когда?

========== ДОПОЛНЕНИЕ ==========

Я категорически не согласен с этим утверждением:

Все зависит от этой строки: std::ifstream input_file(filename); где имя файла представляет собой std::string.

Я полностью СОГЛАСЕН с этим утверждением:

Вы получаете почти ту же ошибку в C#, если у вас есть статические члены класса, которые зависят друг от друга, и они не инициализируются в том порядке, в котором вы ожидаете. В C++, если у вас есть статический синглтон и другой статический член, ссылающийся на него

Вызов «ifstream» сам по себе не является проблемой. Скорее проблема заключается в вызове класса, который вызывает ifstream до того, как программа инициализирует.

Q: Вы называете "новым" в этом классе? Если да, то где. Пожалуйста, вырежьте/вставьте этот код.

Согласно MSDN, вы должны иметь возможность установить "отладку смешанного режима". У меня много разных копий MSVS :) ... но MSVS 2010/C++ не входит в их число. Пожалуйста, посмотрите на эту документацию:

person paulsm4    schedule 05.07.2012
comment
Привет, я сделал это. Точка останова никогда не достигается. Просто наличие конструктора в коде вызывает проблему, даже если он никогда не достигается. Комментируя конструктор, устанавливая для моего ptr значение NULL и выполняя if(ptr != NULL) ptr->SomeFunction(), возникает та же ошибка. - person Constantin; 05.07.2012
comment
Вопрос: Вы явно включили неуправляемую отладку в MSVS IDE? Вопрос. Используете ли вы MSVS 2010 Pro (или выше) или MSVS 2010 Express? Вы используете C++/CLI (управляемый код) или неуправляемый код? - person paulsm4; 05.07.2012
comment
Ганс Пассант также предложил это, однако я не могу найти эту опцию на страницах свойств проекта. Я использую для них управляемый код Form, но он использует неуправляемые библиотеки C++, которые я написал. Большинство из них работают, а этот самый новый - нет, если я использую std::ifstream - person Constantin; 05.07.2012
comment
@Constantin - я добавил новую информацию. Пожалуйста, не фокусируйтесь на std::ifstream ... за возможным исключением, что, возможно, вы вызываете 16-битную версию Unicode ifstream, но код ожидает 8-битную версию ASCII (или наоборот). Но я думаю, что ваше время лучше потратить 1) на то, чтобы отладчик работал, и 2) на поиск экземпляра статического объекта. Я почти уверен, что вы создаете (создаете преждевременно!) ИМХО... И, пожалуйста, опубликуйте еще немного кода, это он даже отдаленно применимо... - person paulsm4; 05.07.2012
comment
Пол, у меня работает отладчик, к сожалению, сторонние библиотеки C++, которые я использую, не поставлялись с библиотеками, скомпилированными для отладки. Таким образом, мои библиотеки, которые вызывают сторонние библиотеки, также скомпилированы Release. Пол, я думаю, ты что-то понял с 8-битным ASCII и 16-битным ASCII. В основном потому, что я удалил ВСЕ вызовы конструктора из своего приложения. Я пересмотрю свой код выше, чтобы показать. - person Constantin; 05.07.2012
comment
Пол, заметьте, я закомментировал новый вызов, AccessViolation все еще существует. Я не могу не подчеркнуть, что это происходит не во время работы программы, а во время загрузки. - person Constantin; 05.07.2012