2016-05-10 4 views
1

Я пытаюсь преобразовать приложение Win32 в DLL. Но у меня есть некоторые трудности с вектором STL. В исходном приложении все работает нормально, но в DLL появляется ошибка «Ошибка чтения». Вот код .hVC++ vector :: push_back "Нарушение доступа" в DLL

#ifdef NNETDLL_EXPORTS 
    #define NNETDLL_API __declspec(dllexport) 
    #else 
    #define NNETDLL_API __declspec(dllimport) 
    #endif 

    #include <vector> 

    using namespace std; 
    #define VECARRAY vector<double> 

    class NNETDLL_API CNNetDll 
    { 
    public: 
     CNNetDll(void); 
     virtual ~CNNetDll(); 

     int m_InputNeurons, m_HiddenNeurons, m_OutputNeurons; 

     /* Активаторы */ 
     vector<double> inputs; 
     vector<double> hidden; 
     vector<double> actual; 

     /* Вход скрытых ячеек(со смещением) */ 
     vector<VECARRAY> who; 

     /* Вход выходных ячеек(со смещением) */ 
     vector<VECARRAY> wih; 

     int InitializeNetwork(CString FileName); 
     void feedForward(); 
     void ActionNN(/*VECARRAY input_vec, VECARRAY& output_vec*/); 
     void ReadNN(CString FileName); 
    }; 

А вот код .cpp, где исключение встречается,

int CNNetDll::InitializeNetwork(CString FileName) 
{ 
    int i, hid, inp, out; 
    CFile f; 
    CString s; 
    TCHAR szDrive[200]; 
    TCHAR szDir[200]; 
    TCHAR szFile[200]; 
    TCHAR szExt[200]; 

    _wsplitpath_s(FileName, szDrive, szDir, szFile, szExt); 
    SetCurrentDirectory(szDir); 
    s = szExt; FileName = szFile + s; 

    f.Open(FileName, CFile::modeRead); 
    f.Read(&m_InputNeurons, sizeof(double)); 
    f.Read(&m_HiddenNeurons, sizeof(double)); 
    f.Read(&m_OutputNeurons, sizeof(double)); 

    for (i = 0; i < m_InputNeurons; i++) 
    { 
     inputs.push_back(0.0); // !!!!! ERROR IS HERE !!!!!! 
    } 
    for (i = 0; i < m_HiddenNeurons; i++) 
    { 
     hidden.push_back(0.0); 
    } 
    for (i = 0; i < m_OutputNeurons; i++) 
    { 
     actual.push_back(0.0); 
    } 
    for (i = 0; i < m_HiddenNeurons + 1; i++) 
    { 
     who.push_back(actual); 
    } 
    for (i = 0; i < m_InputNeurons + 1; i++) 
    { 
     wih.push_back(hidden); 
    } 
    for (hid = 0; hid < m_HiddenNeurons; hid++) 
    { 
     for (inp = 0; inp <= m_InputNeurons; inp++) 
     { 
      f.Read(&wih[inp][hid], sizeof(double)); 
     } 
    } 
    for (out = 0; out < m_OutputNeurons; out++) 
    { 
     for (hid = 0; hid <= m_HiddenNeurons; hid++) 
     { 
      f.Read(&who[hid][out], sizeof(double)); 
     } 
    } 

    f.Close(); 

    return 1; 
} 

приложение падает, пытаясь заполнить вектор. Последний шаг в стеке вызовов в файле «xutility» на этой линии:

inline void _Container_base12::_Orphan_all() 
    { // orphan all iterators 
#if _ITERATOR_DEBUG_LEVEL == 2 
    if (_Myproxy != 0) 
     { // proxy allocated, drain it 
     _Lockit _Lock(_LOCK_DEBUG); 

     for (_Iterator_base12 **_Pnext = &_Myproxy->_Myfirstiter; 
      *_Pnext != 0; *_Pnext = (*_Pnext)->_Mynextiter) // !!!!LAST OPERATION BEFORE EXCEPTION!!! 
      (*_Pnext)->_Myproxy = 0; 
     _Myproxy->_Myfirstiter = 0; 
     } 
#endif /* _ITERATOR_DEBUG_LEVEL == 2 */ 
    } 

Повторяя в исходном приложении everithing отлично работает. Также я замечаю, что ошибка возникает с этим вектором, которое объявляется первым в классе CNNetDll. В приведенном выше коде это векторные «входы». Если я изменю заявления как этот

vector<double> hidden; 
vector<double> actual; 
vector<double> inputs; 

тогда возникает исключение с вектором «скрытый» на этот код

for (i = 0; i < m_InputNeurons; i++) 
{ 
    inputs.push_back(0.0); //!!!! works properly !!!!! 
} 
for (i = 0; i < m_HiddenNeurons; i++) 
{ 
    hidden.push_back(0.0); // !!! exception here !!! 
} 
for (i = 0; i < m_OutputNeurons; i++) 
{ 
    actual.push_back(0.0); 
} 

Оbject создание и вызов функции:

CNNetDll nn; 
nn.InitializeNetwork(_T("M:\\Tasks\\2016\\Win8-64\\AI\\NNet\\Debug\\NN.dat")); 

Как решить эту проблему ????

+2

Вы определили m_InputNeurons, m_HiddenNeurons, m_OutputNeurons как тип INT данных, но хранение размера двойного типа данных к нему. Это приведет к недопустимому доступу к памяти. Измените f.Read (& m_InputNeurons, sizeof (double)); to f.Read (& m_InputNeurons, sizeof (int)); во всех трех f.Read или изменить тип данных m_InputNeurons и т. д., чтобы удвоить. – MNS

+0

Не могу поверить, что проблема была в такой простой вещи, но теперь она работает. Благодарю. Странно, что он отлично работает в приложении .exe и в dll не удается. –

+1

Такие вещи происходят в C++ с необработанными операциями памяти. Три вызова 'f.Read()' будут перезаписываться за пределами размера типа данных 'int', и это может повредить другие переменные-члены, такие как' input', поэтому, когда вы вызываете 'inputs.push_back (0.0);' производится, это вызывает нарушение прав доступа. Ошибка нарушения прав доступа может не произойти точно в точке перезаписывания памяти, это может произойти на более позднем этапе выполнения, и именно это произошло в этом случае. – MNS

ответ

1

Проблема была в определении неправильных переменных (с типом данных int) и сохранении размера двойного типа данных для этих переменных. С соответствующими типами все работает отлично.

int m_InputNeurons, m_HiddenNeurons, m_OutputNeurons; 

 Смежные вопросы

  • Нет связанных вопросов^_^