Dlaczego wywołuje się destruktor klasy cPLUGIN zawartej w vectorze?

0

Witajcie. Tkwię w wątku http://4programmers.net/Forum/C_i_C++/271356-komunikacja_bibliotek_miedzy_soba_i_aplikacja_winapi?p=1254033#comment-294353

Udało mi się nawiązać połączenie z dllką. Zacząłem robić funkcję usuwającą plugin, zamykającą dllkę i napotkałem problem. Otóż zaraz po tym jak dllka zwraca komunikat, że plugin został utworzony (messagebox) zostaje wywołany destruktor klasy cPLUGIN, która jest elementem vectora vPlugins. Nie mam pojęcia zielonego ani czerwonego dlaczego.

Wiem, że proszę o dużo, ale czy ktoś mógłby zerknąć w kod i może znajdzie rozwiązanie mojego problemu? Bo siedzę od wczoraj i nic. Jeżeli nie to nawet prosze o priv co do ceny za pomoc. Pozdrowienia ludziska !

Kod aplikacji obsługującej komunikację między dllkami i pierwszą dllką znajduje się w załączniku.

1

Jeżeli chodzi o usuwanie elementów z tablicy, to realizujesz to źle.

bool cENGINE::f_FreePlugin(string sName){
    for(vector<cPLUGIN>::iterator it = vPlugins.begin(); it != vPlugins.end(); ++it)
        if(it->sName == sName)
           vPlugins.erase(it);
    return false;
} 

Usunięcie elementu modyfikuje pozycje pozostałych elementów w tablicy, więc powinieneś korzystać z iteratora zwracanego przez funkcję erase.

bool cENGINE::f_FreePlugin(string sName){
    for(vector<cPLUGIN>::iterator it = vPlugins.begin(); it != vPlugins.end(); /*++it*/)
        if(it->sName == sName)
            it = vPlugins.erase(it);
        else 
            ++it;
    return false;
} 
3

Ewentualnie możesz skorzystać z idiomu erase-remove, tylko uważaj na to co podajesz funkcji, bo można się naciąć ( http://dev.krzaq.cc/an-erase-remove-idiom-gotcha/ )

0

Problem w tym ze nie używam póki co ten funkcji a i tak element gdzieś jest usuwany

0

W programie masz funkcję GetPtr_vPlugins(), zwracającą wskaźnik do tablicy. Jak wygląda kod, który korzysta z tego wskaźnika?

0

Póki co nigdzie nie używam tej funkcji.

Mam wątek, który obsługuje tablicę wiadomości wysłanych przez pluginy. Wszystkie wiadomości chomikuję w wektorze vMessageQueue.
Jakaś dllka wywołuje funkcję:

bool ENGINE_GetMessage(string sDll, string sMessage, WPARAM wParam, LPARAM lParam) 

a ta funkcja wywołuje metodę:bool cENGINE::f_GetMessage(string sDll, string sMessage, WPARAM wParam, LPARAM lParam){
MessageBox(0, &sDll[0], &sMessage[0], MB_OK);
vMessageQueue.push_back({sDll, sMessage, wParam, lParam});
ActiveServiceMessageThread();
return true;
}

ActiveServiceMessageThread();
```cpp
void __cdecl ServiceMessageThread( void * c ){
    class cENGINE *wsk = (cENGINE *)c;
    if(!wsk)
     _endthread();

    while(!(*(wsk->GetPtr_vMessageQueue())).empty())
    {
        EnterCriticalSection( wsk->GetCriticalSection());
        /**/wsk->f_SendMessage((*(wsk->GetPtr_vMessageQueue()))[0].sDll, (*(wsk->GetPtr_vMessageQueue()))[0].sMessage, (*(wsk->GetPtr_vMessageQueue()))[0].wParam, (*(wsk->GetPtr_vMessageQueue()))[0].lParam);
        LeaveCriticalSection( wsk->GetCriticalSection() );
        (*(wsk->GetPtr_vMessageQueue())).erase((*(wsk->GetPtr_vMessageQueue())).begin());
    }

    wsk->EndServiceMessageThread();
    _endthread();
} 

Z kolei ona wysyła każdą wiadomość z kolei do każdej dllki przez:

bool cENGINE::f_SendMessage(string sDll, string sMessage, WPARAM wParam, LPARAM lParam){
    for(auto &el : vPlugins)
     if(el.sName != sDll)
      if(!el.hSendMessage && !el.hSendMessage(sDll, sMessage, wParam, lParam))
       return false;
    return true;
} 
0

A nie powinieneś aby operować na tablicy vMessageQueue w sekcji krytycznej?

0

Postanawiam zmienić vector <cPlugin> na vector <cPlugin * >. Tylko piszecie mi cały czas, że używanie new i delete jest złe i sie przejąłem. Czytam o shared_ptr, unique i weak https://pl.wikibooks.org/wiki/C%2B%2B/Zarz%C4%85dzanie_pami%C4%99ci%C4%85 ale nie wiem czy to jest to co ma być... Help me :(

0

panowie no... Zmieniłem tak jak w powyższym poście i wszystko mi działa. Ale dlaczego?
EDIT:
A jednak nie...

0
extern "C" DLL_EXPORT BOOL APIENTRY DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
{
    switch (fdwReason)
    {
        case DLL_PROCESS_ATTACH:
            // attach to process
            // return FALSE to fail DLL load
            break;
        case DLL_PROCESS_DETACH:
            delete Plugin;
            MessageBox(0, "process detach", "dll", MB_OK);
            break;

        case DLL_THREAD_ATTACH:
            // attach to thread
            break;

        case DLL_THREAD_DETACH:
            // detach from thread
            break;
    }
    return TRUE; // succesful
} 

Kiey jest wywoływany DLL_THREAD_DETACH ?

0

Dlaczego w petli for zmienna it wskazuje na wskaźnik do obiektu a nie iterator? :O

for(auto it : vPlugins){
        MessageBox(0, (it->sName).c_str(), "main tekst", MB_OK);
        if(it->sName == sName){
            MessageBox(0, "udalo sie usunac plugin", "main", MB_OK);
            delete it;
            vPlugins.erase(it);
    }} 

C:\Users\Świdwa\Desktop\ODTWARZACZ\Cialo programu\main.cpp|103|error: no matching function for call to 'std::vector<cPLUGIN*>::erase(cPLUGIN*&)'|

1

W ranged forze iterujesz po elementach, nie iteratorach (tutaj po kopiach elementów, konkretnie)

0

Kurczę, ale z tym przykładem z linku twojego mam problem. Cos tu jest nie tak : /

for(auto it : vPlugins){
        MessageBox(0, (it->sName).c_str(), "main tekst", MB_OK);
        if(it->sName == sName){
            MessageBox(0, "udalo sie usunac plugin", "main", MB_OK);
            //vPlugins.erase(find(vPlugins.begin(), vPlugins.end(), vPlugins));
            vPlugins.erase(remove_if(vPlugins.begin(), vPlugins.end(),
                [it](vector<cPLUGIN *>::iterator const msg){
                return (it == *msg);
            }));
            delete it;
    }} 

m:

0

Tak, zrobiłeś dokładnie to, przed czym ostrzegałem :D

            vPlugins.erase(remove_if(vPlugins.begin(), vPlugins.end(),
                [it](vector<cPLUGIN *>::iterator const msg){
                return (it == *msg);
            }), /* --> */ vPlugins.end() /* <-- */ );

Edit: chyba, że nie tylko o to chodzi. Jakiego typu jest vPlugins? Predykat powinien przyjmować decltype(vPlugins)::value_type - jeśli to jest vector<vector<cPLUGIN*>::iterator> to jest ok.

1 użytkowników online, w tym zalogowanych: 0, gości: 1