2016-05-10 1 views
1

Je tente de transformer une application Win32 en une DLL. Mais j'ai quelques difficultés avec le vecteur STL. Dans l'application originale tout fonctionne très bien, mais dans DLL "Access violation de lecture emplacement" erreur se produit. Voici le code de .hVC++ vector :: push_back "Violation d'accès" dans la 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); 
    }; 

Et voici le code de cpp, où une exception 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; 
} 

L'application tombe en essayant de remplir le vecteur. La dernière étape est callstack dans le fichier « xutility » sur ces lignes:

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

Répétition, dans everithing l'application d'origine fonctionne très bien. Aussi je remarque, que l'erreur se pose avec ce vecteur, quelle déclaration va d'abord dans la classe CNNetDll. Dans le code ci-dessus c'est le vecteur "entrées". Si je change des déclarations comme celui-ci

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

alors l'exception se pose avec le vecteur "caché" sur ce 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); 
} 

création Оbject et la fonction appel:

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

Comment résoudre ce problème ????

+2

Vous avez défini m_InputNeurons, m_HiddenNeurons, m_OutputNeurons comme type de données int, mais le stockage de la taille du type de données double à elle. Cela entraînera un accès mémoire invalide. Changez f.Read (& m_InputNeurons, sizeof (double)); à f.Read (& m_InputNeurons, sizeof (int)); dans tous les trois f.Read ou changer le type de données de m_InputNeurons etc pour doubler. – MNS

+0

Ne peut pas croire que le problème était là dans une chose si simple, mais maintenant cela fonctionne. Merci. Étrange que cela fonctionne parfaitement dans l'application .exe et dans la DLL échoue. –

+1

De telles choses se produisent en C++ avec des opérations de mémoire brutes. Les trois appels 'f.Read()' écraseront au-delà de la taille du type de données 'int' et pourraient corrompre d'autres variables membres telles que' inputs' alors quand appel à 'inputs.push_back (0.0);' est fait, il provoque une violation d'accès. Erreur de violation d'accès peut ne pas se produire exactement au moment de l'écrasement de la mémoire, il peut arriver à un point d'exécution ultérieur et c'est ce qui s'est passé dans ce cas. – MNS

Répondre

1

Le problème résidait dans la définition de variables incorrectes (avec le type de données int) et le stockage de la taille du type de données double dans ces variables. Les types correspondants fonctionnent parfaitement.

int m_InputNeurons, m_HiddenNeurons, m_OutputNeurons;