CYFROWY BARON • PROGRAMOWANIE • Zobacz wątek - DLL ładowana dynamicznie i TListView

DLL ładowana dynamicznie i TListView

problemy z funkcjonowaniem bibliotek, komponentów itp.

DLL ładowana dynamicznie i TListView

Nowy postprzez Darek_C++ » niedziela, 12 grudnia 2010, 10:57

Witam ponownie,
Kod testowej biblioteki dll mającej za zadanie umieścić danych w TListView jest następujący:
KOD cpp:     UKRYJ  
#include <vcl.h>
#include <windows.h>
#pragma hdrstop

#pragma argsused

extern "C" __declspec(dllexport) void __stdcall DoTestDll(TListView* );

int WINAPI DllEntryPoint(HINSTANCE hinst, unsigned long reason, void* lpReserved)
{
        return 1;
}
//---------------------------------------------------------------------------
void __stdcall DoTestDll(TListView* ListView1)
{
        for (int jj=1; jj <= 10; jj++)
        {
                TListItem * ElementListy = ListView1->Items->Add();
                ElementListy->Caption = "Dane z DLL: "+(String) jj;
                ElementListy->SubItems->Add("---");
        }
}


Testowy kod formularza wywołujący funkcję z DLL'ki:
KOD cpp:     UKRYJ  
#include <vcl.h>
#pragma hdrstop

#include "Unit1.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.dfm"

//#pragma comment(lib, "TestDll.lib")

TForm3 *Form3;

//extern "C" __declspec(dllimport) void __stdcall DoTestDll(TListView *);

//---------------------------------------------------------------------------
__fastcall TForm3::TForm3(TComponent* Owner)
        : TForm(Owner)
{
}
//---------------------------------------------------------------------------
void __fastcall TForm3::Button2Click(TObject *Sender)
{

        for (int jj=1; jj <= 10; jj++)
        {

                TListItem * ElementListy = ListView1->Items->Add();
                ElementListy->Caption = "Dane: "+(String) jj;
                ElementListy->SubItems->Add("---");
        }
}
//---------------------------------------------------------------------------
void __fastcall TForm3::Button3Click(TObject *Sender)
{
        //DoTestDll(ListView1);
}
//---------------------------------------------------------------------------
void __fastcall TForm3::Button4Click(TObject *Sender)
{
        typedef void ( * pcDoDll )( TListView *ListView1 );
        HINSTANCE biblio = LoadLibrary("TestDll.dll");
        if (biblio == NULL)
        {
                ShowMessage("Brak pliku");
        }
        else
        {
                pcDoDll _WykonajZDll = (pcDoDll)GetProcAddress(biblio,"DoTestDll");

                if (_WykonajZDll !=NULL)
                {
                        _WykonajZDll(ListView1);
                }
        }
        FreeLibrary(biblio);
}
//---------------------------------------------------------------------------
void __fastcall TForm3::Button1Click(TObject *Sender)
{
        Application->Terminate();      
}


Problem jest taki, że przy wywoływaniu funkcji z DLL ładowanego dynamicznie dane są wczytane do TlistView, ale przy zamykaniu formularza [ okna programu] wywalany jest wyjątek do tego dwa razy ten sam:

"First chance exception at $7C812AFB. Exception class EAccessViolation with message 'Access violation at address 0042A23D in module 'Project1Formularz.exe'. Write of address 00D206CC'. Process Project1Formularz.exe (2620)"



Jeśli wykomentuję zwalnianie biblioteki DLL -> //FreeLibrary(biblio); wyjątek nie jest emitowany, ale tak być nie może.

Pytanie brzmi dlaczego tak się dzieje :(
Nie masz wystarczających uprawnień, aby zobaczyć pliki załączone do tego postu.
Ostatnio edytowano niedziela, 12 grudnia 2010, 11:14 przez Darek_C++, łącznie edytowano 1 raz
Avatar użytkownika
Darek_C++
Elektrowied
Elektrowied
 
Posty: 454
Dołączył(a): piątek, 25 lipca 2008, 14:33
Podziękował : 66
Otrzymał podziękowań: 4
System operacyjny: Windows XP Pro SP2
Kompilator: Turbo Explorer C++
Gadu Gadu: 0
    Windows XPFirefox

Re: DLL ładowana dynamicznie i TListView

Nowy postprzez Cyfrowy Baron » niedziela, 12 grudnia 2010, 11:13

Biblioteka tylko pozornie jest częścią aplikacji, w rzeczywistości jest odrębnym procesem. Wykorzystując bibliotekę ładujesz do ListView w aplikacji dane poprzez argument funkcji w bibliotece, więc przesyłasz ListView z aplikacji do biblioteki. Występuje tutaj jakiś wyciek pamięci, ale nie bardzo go rozumiem. Jeżeli zwolnisz bibliotekę przed zamknięciem aplikacji, to wyciek nie powinien się pojawić, jeżeli jednak w chwili zamykania aplikacji biblioteka nie jest zwolniona, to oczywiście jest wyciek, gdyż ListView z aplikacji znajduje się w bibliotece, aplikacja przy zamknięciu niszczy wszystkie swoje obiekty, ale nie może zniszczyć obiektu w bibliotece.
Nie jestem pewien czy tak jest, niech kto inny się wypowie.
Avatar użytkownika
Cyfrowy Baron
Administrator
Administrator
 
Posty: 4716
Dołączył(a): niedziela, 13 lipca 2008, 15:17
Podziękował : 12
Otrzymał podziękowań: 442
System operacyjny: Windows 7 x64 SP1
Kompilator: Embarcadero RAD Studio XE2
C++ Builder XE2 Update 4
SKYPE: cyfbar
Gadu Gadu: 0
    Windows XPFirefox

Re: DLL ładowana dynamicznie i TListView

Nowy postprzez Darek_C++ » niedziela, 12 grudnia 2010, 11:15

Jeśli wykomentuję zwalnianie biblioteki DLL -> //FreeLibrary(biblio); wyjątek nie jest emitowany, ale tak być nie może.
Avatar użytkownika
Darek_C++
Elektrowied
Elektrowied
 
Posty: 454
Dołączył(a): piątek, 25 lipca 2008, 14:33
Podziękował : 66
Otrzymał podziękowań: 4
System operacyjny: Windows XP Pro SP2
Kompilator: Turbo Explorer C++
Gadu Gadu: 0
    Windows XPFirefox

Re: DLL ładowana dynamicznie i TListView

Nowy postprzez Cyfrowy Baron » niedziela, 12 grudnia 2010, 11:19

Jeśli wykomentuję zwalnianie biblioteki DLL -> //FreeLibrary(biblio); wyjątek nie jest emitowany, ale tak być nie może.


To mi podsuwa pewne podejrzenia. Wykomentuj tą linię, ale zamiast zamykać aplikację komendą Application->Terminate() zamknij ją krzyżykiem, lub poleceniem Close(), a następnie opisz efekty.
Avatar użytkownika
Cyfrowy Baron
Administrator
Administrator
 
Posty: 4716
Dołączył(a): niedziela, 13 lipca 2008, 15:17
Podziękował : 12
Otrzymał podziękowań: 442
System operacyjny: Windows 7 x64 SP1
Kompilator: Embarcadero RAD Studio XE2
C++ Builder XE2 Update 4
SKYPE: cyfbar
Gadu Gadu: 0
    Windows XPFirefox

Re: DLL ładowana dynamicznie i TListView

Nowy postprzez Darek_C++ » niedziela, 12 grudnia 2010, 11:22

Jeśli biblioteka nie jest zwalniana czyli daje:
// FreeLibrary(biblio);
przy zamykaniu krzyżykiem okna jak i Application->Terminate(); wyjątek nie jest emitowany.
-------
Jeszcze dziwniejsze jest to, że jak odkomentuje kod realizujący ładowanie statyczne czyli:
#pragma comment(lib, "TestDll.lib")
extern "C" __declspec(dllimport) void __stdcall DoTestDll(TListView *);
DoTestDll(ListView1);
Wyjątek nie jest emitowany :)

Chyba, że znowu zakomentuję
//DoTestDll(ListView1);
i pojawia się wyjątek co IMHO świadczy o tym, że jej samo dołączenie statyczne nic nie zmienia.
Avatar użytkownika
Darek_C++
Elektrowied
Elektrowied
 
Posty: 454
Dołączył(a): piątek, 25 lipca 2008, 14:33
Podziękował : 66
Otrzymał podziękowań: 4
System operacyjny: Windows XP Pro SP2
Kompilator: Turbo Explorer C++
Gadu Gadu: 0
    Windows XPFirefox

Re: DLL ładowana dynamicznie i TListView

Nowy postprzez Cyfrowy Baron » niedziela, 12 grudnia 2010, 11:28

Wydaje mi się, że to oznacza, iż po zwolnieniu biblioteki ListView pozostaje w niej, więc aplikacja przy zamykaniu nie ma do niego dostępu, co wywołuje błąd. Oczywiście zgaduję.
Podam przykład dynamicznego ładowania i zwalniania biblioteki z pliku pomocy C++Builder 2010. Spróbuj przerobić to na ten sposób:

KOD cpp:     UKRYJ  
// A simple program that uses LoadLibrary and
// GetProcAddress to access myPuts from Myputs.dll.
 
#include <stdio.h>
#include <windows.h>
 
typedef int (*MYPROC)(LPTSTR);
 
VOID main(VOID)
{
    HINSTANCE hinstLib;
    MYPROC ProcAdd;
    BOOL fFreeResult, fRunTimeLinkSuccess = FALSE;
 
    // Get a handle to the DLL module.
 
    hinstLib = LoadLibrary(TEXT("myputs"));
 
    // If the handle is valid, try to get the function address.
 
    if (hinstLib != NULL)
    {
        ProcAdd = (MYPROC) GetProcAddress(hinstLib, TEXT("myPuts"));
 
        // If the function address is valid, call the function.
 
        if (NULL != ProcAdd)
        {
            fRunTimeLinkSuccess = TRUE;
            (ProcAdd) (TEXT("Message via DLL function\n"));
        }
 
        // Free the DLL module.
 
        fFreeResult = FreeLibrary(hinstLib);
    }
 
    // If unable to call the DLL function, use an alternative.
 
    if (! fRunTimeLinkSuccess)
        printf("Message via alternative method\n");
}
 
Avatar użytkownika
Cyfrowy Baron
Administrator
Administrator
 
Posty: 4716
Dołączył(a): niedziela, 13 lipca 2008, 15:17
Podziękował : 12
Otrzymał podziękowań: 442
System operacyjny: Windows 7 x64 SP1
Kompilator: Embarcadero RAD Studio XE2
C++ Builder XE2 Update 4
SKYPE: cyfbar
Gadu Gadu: 0
    Windows XPFirefox

Re: DLL ładowana dynamicznie i TListView

Nowy postprzez Darek_C++ » niedziela, 12 grudnia 2010, 11:39

Dałem taki kod:
KOD cpp:     UKRYJ  
void __fastcall TForm3::Button5Click(TObject *Sender)
{
        typedef int (*MYPROC)(TListView *);
        HINSTANCE hinstLib;
        MYPROC ProcAdd;
    BOOL fFreeResult, fRunTimeLinkSuccess = FALSE;
 
    // Get a handle to the DLL module.
 
        hinstLib = LoadLibrary("TestDll.dll");
 
    // If the handle is valid, try to get the function address.
 
    if (hinstLib != NULL)
        {
                //pcDoDll _WykonajZDll = (pcDoDll)GetProcAddress(biblio,"DoTestDll");
                ProcAdd = (MYPROC) GetProcAddress(hinstLib, "DoTestDll");
 
        // If the function address is valid, call the function.
 
        if (NULL != ProcAdd)
        {
            fRunTimeLinkSuccess = TRUE;
                        ShowMessage("Message via DLL function");
                }

 
        // Free the DLL module.
 
        fFreeResult = FreeLibrary(hinstLib);
    }
 
    // If unable to call the DLL function, use an alternative.
 
    if (! fRunTimeLinkSuccess)
                ShowMessage("Message via alternative method");
}
Ale jak wywołać teraz funkcję z DLL'ki ?
Avatar użytkownika
Darek_C++
Elektrowied
Elektrowied
 
Posty: 454
Dołączył(a): piątek, 25 lipca 2008, 14:33
Podziękował : 66
Otrzymał podziękowań: 4
System operacyjny: Windows XP Pro SP2
Kompilator: Turbo Explorer C++
Gadu Gadu: 0
    Windows XPFirefox

Re: DLL ładowana dynamicznie i TListView

Nowy postprzez Cyfrowy Baron » niedziela, 12 grudnia 2010, 11:44

To oczywiście nic nie daje, źle go przekształciłeś, ale to co napisałeś pierwotnie odpowiada temu co jest w przykładzie, więc nie mam chwilowo żadnych pomysłów.
Avatar użytkownika
Cyfrowy Baron
Administrator
Administrator
 
Posty: 4716
Dołączył(a): niedziela, 13 lipca 2008, 15:17
Podziękował : 12
Otrzymał podziękowań: 442
System operacyjny: Windows 7 x64 SP1
Kompilator: Embarcadero RAD Studio XE2
C++ Builder XE2 Update 4
SKYPE: cyfbar
Gadu Gadu: 0
    Windows XPFirefox

Re: DLL ładowana dynamicznie i TListView

Nowy postprzez Darek_C++ » niedziela, 12 grudnia 2010, 12:01

Dobrze, że linkowanie statyczne DLL w tym wypadku nie powoduje przedmiotowego błędu :)
Avatar użytkownika
Darek_C++
Elektrowied
Elektrowied
 
Posty: 454
Dołączył(a): piątek, 25 lipca 2008, 14:33
Podziękował : 66
Otrzymał podziękowań: 4
System operacyjny: Windows XP Pro SP2
Kompilator: Turbo Explorer C++
Gadu Gadu: 0
    Windows XPFirefox

Re: DLL ładowana dynamicznie i TListView

Nowy postprzez polymorphism » niedziela, 12 grudnia 2010, 12:04

Cyfrowy Baron napisał(a):Biblioteka tylko pozornie jest częścią aplikacji, w rzeczywistości jest odrębnym procesem.

Ejże, ejże. Żadnym oddzielnym procesem! DLL-ka jest częścią aplikacji, ponieważ leży w tej samej przestrzeni adresowej, w przeciwieństwie do procesu, który ma swoją własną przestrzeń. Błąd zapewne polega na tym, że aplikacja i biblioteka korzystają z różnych stert. Z tego co pamiętam, trzeba było jakiś nagłówek załączyć, żeby nie było z tym problemów, choć nie wiem, czy rozwiązałoby to problem w przypadku łączenia w run-time'ie.
C++ Reference - opis wszystkich klas STL-a i funkcji C.
Avatar użytkownika
polymorphism
Doświadczony Programista ● Moderator
Doświadczony Programista ● Moderator
 
Posty: 2156
Dołączył(a): piątek, 19 grudnia 2008, 13:04
Podziękował : 0
Otrzymał podziękowań: 200
System operacyjny: Windows 8.1
Windows 10
Linux Mint 21.1
Kompilator: Visual Studio
Visual Studio Code
MSYS2 (MinGW, clang)
g++
clang
Gadu Gadu: 0
    Windows XPFirefox

Re: DLL ładowana dynamicznie i TListView

Nowy postprzez Cyfrowy Baron » niedziela, 12 grudnia 2010, 12:16

polymorphism napisał(a):Żadnym oddzielnym procesem! DLL-ka jest częścią aplikacji, ponieważ leży w tej samej przestrzeni adresowej,


adress.png


Tutaj masz rację, co widać na przykładzie wyżej. Zasugerowałem się tym, że biblioteka ma odrębny adres.



Co się tyczy problemu, to może takie rozwiązanie w bibliotece:

KOD cpp:     UKRYJ  
#incldue <memory>
TListView *__stdcall DoTestDll(void)
{
  std::auto_ptr<TListView> ListView1 ( new TListView(NULL) );

        for (int jj=1; jj <= 10; jj++)
        {
                TListItem * ElementListy = ListView1->Items->Add();
                ElementListy->Caption = "Dane z DLL: "+(String) jj;
                ElementListy->SubItems->Add("---");
        }

 return ListView1.release();
}


Obiekt powstaje w bibliotece i w niej jest zwalniany.
Nie masz wystarczających uprawnień, aby zobaczyć pliki załączone do tego postu.
Avatar użytkownika
Cyfrowy Baron
Administrator
Administrator
 
Posty: 4716
Dołączył(a): niedziela, 13 lipca 2008, 15:17
Podziękował : 12
Otrzymał podziękowań: 442
System operacyjny: Windows 7 x64 SP1
Kompilator: Embarcadero RAD Studio XE2
C++ Builder XE2 Update 4
SKYPE: cyfbar
Gadu Gadu: 0
    Windows XPFirefox

Re: DLL ładowana dynamicznie i TListView

Nowy postprzez Darek_C++ » niedziela, 12 grudnia 2010, 12:27

Po dodaniu w DLL
KOD cpp:     UKRYJ  
TListView *__stdcall DoTestDll(void)
{
  std::auto_ptr<TListView> ListView1 ( new TListView(NULL) );

                for (int jj=1; jj <= 10; jj++)
                {
                TListItem * ElementListy = ListView1->Items->Add();
                                ElementListy->Caption = "Dane z DLL: "+(String) jj;
                                ElementListy->SubItems->Add("---");
                }

 return ListView1.release();
}

nie mogę tego kodu skompilować z powodu błędów: w -> LINI-> std::auto_ptr<TListView> ListView1 ( new TListView(NULL) );


[C++ Error] UnitTestDll.cpp(32): E2015 Ambiguity between '_fastcall Comctrls::TListView::TListView(Classes::TComponent *)' and '_fastcall Comctrls::TListView::TListView(void *)'

Avatar użytkownika
Darek_C++
Elektrowied
Elektrowied
 
Posty: 454
Dołączył(a): piątek, 25 lipca 2008, 14:33
Podziękował : 66
Otrzymał podziękowań: 4
System operacyjny: Windows XP Pro SP2
Kompilator: Turbo Explorer C++
Gadu Gadu: 0
    Windows XPFirefox

Re: DLL ładowana dynamicznie i TListView

Nowy postprzez Cyfrowy Baron » niedziela, 12 grudnia 2010, 12:39

Wiec zmień nagłówek funkcji:

KOD cpp:     UKRYJ  
TListView *__fastcall DoTestDll(void)
Avatar użytkownika
Cyfrowy Baron
Administrator
Administrator
 
Posty: 4716
Dołączył(a): niedziela, 13 lipca 2008, 15:17
Podziękował : 12
Otrzymał podziękowań: 442
System operacyjny: Windows 7 x64 SP1
Kompilator: Embarcadero RAD Studio XE2
C++ Builder XE2 Update 4
SKYPE: cyfbar
Gadu Gadu: 0
    Windows XPFirefox

Re: DLL ładowana dynamicznie i TListView

Nowy postprzez Darek_C++ » niedziela, 12 grudnia 2010, 12:43

Bez zmian :(
Nawet w formularzu:
KOD cpp:     UKRYJ  
void __fastcall TForm3::Button5Click(TObject *Sender)
{
        std::auto_ptr<TListView> ListView1 (new TListView(NULL) ); // <- Tuaj
}


[C++ Error] Unit1.cpp(74): E2015 Ambiguity between '_fastcall Comctrls::TListView::TListView(Classes::TComponent *)' and '_fastcall Comctrls::TListView::TListView(void *)'

Avatar użytkownika
Darek_C++
Elektrowied
Elektrowied
 
Posty: 454
Dołączył(a): piątek, 25 lipca 2008, 14:33
Podziękował : 66
Otrzymał podziękowań: 4
System operacyjny: Windows XP Pro SP2
Kompilator: Turbo Explorer C++
Gadu Gadu: 0
    Windows XPFirefox

Re: DLL ładowana dynamicznie i TListView

Nowy postprzez Cyfrowy Baron » niedziela, 12 grudnia 2010, 12:51

To przez to NULL. Obiekt musi być przypisany do jakiegoś formularza. Nie mam pomysłu.
Avatar użytkownika
Cyfrowy Baron
Administrator
Administrator
 
Posty: 4716
Dołączył(a): niedziela, 13 lipca 2008, 15:17
Podziękował : 12
Otrzymał podziękowań: 442
System operacyjny: Windows 7 x64 SP1
Kompilator: Embarcadero RAD Studio XE2
C++ Builder XE2 Update 4
SKYPE: cyfbar
Gadu Gadu: 0
    Windows XPFirefox

Następna strona

  • Podobne tematy
    Odpowiedzi
    Wyświetlone
    Ostatni post

Powrót do Biblioteki i komponenty

Kto przegląda forum

Użytkownicy przeglądający ten dział: Brak zalogowanych użytkowników i 2 gości

cron