2016-05-10 16 views
1

Ich versuche, eine Win32-Anwendung in eine DLL zu transformieren. Aber ich habe einige Schwierigkeiten mit dem STL-Vektor. In der ursprünglichen Anwendung funktioniert alles einwandfrei, aber in der DLL "Access violation reading location" tritt der Fehler auf. Hier ist der Code von .hVC++ vector :: push_back "Zugriffsverletzung" in 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); 
    }; 

Und hier ist der Code von CPP, wo eine Ausnahme occures

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; 
} 

Die App fällt versuchen, den Vektor zu füllen. Der letzte Schritt in Aufrufliste ist in "xutility" Datei auf diesen Zeilen:

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 */ 
    } 

Wiederholung, in ursprünglicher Anwendung everithing funktioniert gut. Auch merke ich, dass der Fehler bei diesem Vektor auftritt, welche Deklaration zuerst in der CNNetDll Klasse geht. Im obigen Code ist es Vektor "Eingänge". Wenn ich Erklärungen wie diese

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

ändern dann stellt sich die Ausnahme mit Vektor "versteckt" auf diesem Code

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 Erstellung und Funktionsaufruf:

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

Wie dieses Problem lösen ????

+2

Sie haben m_InputNeurons, m_HiddenNeurons, m_OutputNeurons als int-Datentyp definiert, speichern aber die Größe des doppelten Datentyps. Dies führt zu ungültigem Speicherzugriff. Ändern Sie f.Read (& m_InputNeurons, sizeof (double)); zu f.Read (& m_InputNeurons, sizeof (int)); in allen drei f.Lesen oder ändern Sie den Datentyp von m_InputNeurons usw. zu verdoppeln. – MNS

+0

Ich kann nicht glauben, dass das Problem so einfach war, aber jetzt funktioniert es. Vielen Dank. Seltsam, dass es in .exe Anwendung und in dll funktioniert fehlschlägt. –

+1

Solche Dinge passiert in C++ mit Raw-Speicher-Operationen. Die drei 'f.Read()' Aufrufe überschreiben die Größe des Datentyps 'int' und können andere Member-Variablen wie' inputs' beschädigen, wenn also ein Aufruf von 'inputs.push_back (0.0);' vorgenommen wird verursacht Zugriffsverletzung. Der Zugriffsverletzungsfehler tritt möglicherweise nicht genau zum Zeitpunkt des Speicherüberschreibens auf, er kann zu einem späteren Zeitpunkt der Ausführung auftreten, und genau das ist in diesem Fall passiert. – MNS

Antwort

1

Das Problem lag in der Definition falscher Variablen (mit dem Datentyp int) und in der Speicherung der Größe des doppelten Datentyps für diese Variablen. Bei übereinstimmenden Typen funktioniert alles einwandfrei.