Dynamiczny TPanel: Access Violation

dział ogólny

Dynamiczny TPanel: Access Violation

Nowy postprzez wargo » sobota, 10 października 2009, 18:29

Kolejne na pewno proste głupie pytanie świadczące o tym że mam za mało pojęcia o programowaniu ^^

Mam problem z dynamicznie tworzonym komponentem TPanel. Kiedy skompiluję poniższy kod, otrzymuję komunikat "Access violation(...)".
Kod: Zaznacz cały
void __fastcall TForm1::MODPLClick(TObject *Sender)
{
static bool WDPLCreated = false;
if(WDPLCreated == false)
{
TPanel *DPL = new TPanel(Form1);
DPL->Width = 10;
DPL->Align = alLeft;
DPL->DockSite = true;
}

if(MODPL->Checked == false)
{
(dynamic_cast<TPanel *>(FindComponent("DPL")))->Show();
Memo1->Left = 10;
MODPL->Checked = true;
}

if(MODPL->Checked == true)
{
(dynamic_cast<TPanel *>(FindComponent("DPL")))->Hide();
Memo1->Left = 0;
MODPL->Checked = false;
}
}

Memo1 - jakiś komponent, tu przykład na Memo1
MODPL - TMenuItem
DPL - Nowy komponent TPanel
WDPLCreated - zapobiega wielokrotnemu tworzeniu TPanel.

I czy polecacie sposób z pojedynczym tworzeniem czy może lepiej po zamknięciu panelu go usuwać za pomocą delete? To raczej powinno zależeć od zastosowania ale może są jakieś zastrzeżenia?
Avatar użytkownika
wargo
Mądrosław
Mądrosław
 
Posty: 389
Dołączył(a): niedziela, 13 lipca 2008, 16:44
PodziÄ™kowaÅ‚ : 12
OtrzymaÅ‚ podziÄ™kowaÅ„: 3
System operacyjny: Windows 7
Kompilator: C++ Builder 6 Personal
Gadu Gadu: 6259515
    NieznanyNieznana

Re: Dynamiczny TPanel: Access Violation

Nowy postprzez Witold » sobota, 10 października 2009, 18:58

wargo napisał(a):Kiedy skompiluję poniższy kod, otrzymuję komunikat "Access violation(...)".


FindComponent szuka po właściwości Name ( DPL->Name = "DPL";), nie ustawiłeś jej. Nie sprawdzasz co zwraca FindComponent i dynamic_cast (zwraca 0 gdy rzutowanie się nie uda). WDPLCreated ma być cały czas false?
Avatar użytkownika
Witold
Konstrukcjonista
Konstrukcjonista
 
Posty: 223
Dołączył(a): piątek, 29 sierpnia 2008, 10:53
PodziÄ™kowaÅ‚ : 1
OtrzymaÅ‚ podziÄ™kowaÅ„: 14
Kompilator: bcb6, Turbo C++ Explorer
    NieznanyNieznana

Re: Dynamiczny TPanel: Access Violation

Nowy postprzez wargo » sobota, 10 października 2009, 19:52

Witold napisał(a):WDPLCreated ma być cały czas false?

Nie, dlatego jest static
Avatar użytkownika
wargo
Mądrosław
Mądrosław
 
Posty: 389
Dołączył(a): niedziela, 13 lipca 2008, 16:44
PodziÄ™kowaÅ‚ : 12
OtrzymaÅ‚ podziÄ™kowaÅ„: 3
System operacyjny: Windows 7
Kompilator: C++ Builder 6 Personal
Gadu Gadu: 6259515
    NieznanyNieznana

Re: Dynamiczny TPanel: Access Violation

Nowy postprzez Cyfrowy Baron » sobota, 10 października 2009, 20:20

Kod: Zaznacz cały
if(WDPLCreated == false)
{
TPanel *DPL = new TPanel(Form1);
DPL->Width = 10;
DPL->Align = alLeft;
DPL->DockSite = true;
}


Nie chce mi się analizować całego kodu, gdyż już w tym fragmencie widzę potencjalne niebezpieczeństwo. Jeżeli tworzysz jakiś obiekt w bloku warunku (tutaj if(){obiekt;) to taki obiekt nie jest dostępny poza tym warunkiem, a to oznacza, że nie mozna w żaden sposób odwoływać się do tegoż obiektu, gdyż zawsze zwróci to błąd z dostępem do pamięci.

Musisz rozwiązać ten problem inaczej.

Jeżeli obiekt DPL ma być dostępny globalnie to musi byc zadeklarowany globalnie, czyli w pliku nagłówkowym w sekcji private lub public. Jeżeli deklarujesz go lokalnie, to jest dostępny lokalnie. Zadeklarowany wewnątrz funkcji, nie jest dostępny poza tą funkcją. Zadeklarowany w bloku warunkowym, nie jest dostępny poza tym blokiem.
Kolejna sprawa to definicja. Obiekt jest dostępny dopiero po zdefiniowaniu, jeżlei będziesz próbował odwoływać się do niego przed zdefiniowaniem, to zawsze otrzymasz błąd dostępu do pamieci.

TPanel *DLP; // deklaracja

DLP = new TPanel(this); // definicja

TPanel *DLP = new TPanel(this); // deklaracja i definicja

Nie wystarczy przypisać obiektu do formularza (new TPanel(Form1)), trzeba mu jeszcze przypisać rodzica:
Kod: Zaznacz cały
{
TPanel *DPL = new TPanel(Form1);
DPL->Parent = Form1;
DPL->Width = 10;
DPL->Align = alLeft;
DPL->DockSite = true;
}


To tyle (na razie). Prawdopodobnie będziesz miał więcej błędów z tym dynamicznym tworzeniem obiektów (nie rozumiesz zasady), ale najpierw uporaj się z tym co napisałem.

Za ten post autor Cyfrowy Baron otrzymał podziękowanie od:
wargo
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
    NieznanyNieznana

Re: Dynamiczny TPanel: Access Violation

Nowy postprzez wargo » niedziela, 11 października 2009, 10:18

polymorphism napisał(a):
DLP = new TPanel(this); // definicja

A ten dalej swoje ;)

Kto?
Avatar użytkownika
wargo
Mądrosław
Mądrosław
 
Posty: 389
Dołączył(a): niedziela, 13 lipca 2008, 16:44
PodziÄ™kowaÅ‚ : 12
OtrzymaÅ‚ podziÄ™kowaÅ„: 3
System operacyjny: Windows 7
Kompilator: C++ Builder 6 Personal
Gadu Gadu: 6259515
    NieznanyNieznana

Re: Dynamiczny TPanel: Access Violation

Nowy postprzez wargo » niedziela, 11 października 2009, 10:58

polymorphism napisał(a):Ta uwaga nawiązuje do innego wątka, gdzie te sprawy były poruszane i, jak mi się wydawało, w jakimś stopniu uporządkowane.

Tylko nie "klasy w dll" :[
Avatar użytkownika
wargo
Mądrosław
Mądrosław
 
Posty: 389
Dołączył(a): niedziela, 13 lipca 2008, 16:44
PodziÄ™kowaÅ‚ : 12
OtrzymaÅ‚ podziÄ™kowaÅ„: 3
System operacyjny: Windows 7
Kompilator: C++ Builder 6 Personal
Gadu Gadu: 6259515
    NieznanyNieznana

Re: Dynamiczny TPanel: Access Violation

Nowy postprzez Cyfrowy Baron » niedziela, 11 października 2009, 11:19

A ten dalej swoje ;)


http://sasq.programuj.com/pl/Code/CPP1/Deklaracje.html
http://pl.wikibooks.org/wiki/C%2B%2B/Czym_jest_obiekt
http://docs.google.com/gview?a=v&q=cache:ZlgngTv5_5QJ:math.hosted.pl/math_2/programowanie_obiektowe/3Klasy.pdf+definicja+obiektu+deklaracja+obiektu&hl=pl&sig=AFQjCNHrMww5a0HrGR9ZaRJgaF0zS_NgAg



http://pl.wikipedia.org/wiki/Zmienna_wska%C5%BAnikowa#Definicja_wska.C5.BAnika_na_obiekt_lub_.28prost.C4.85.29_zmienn.C4.85


int* p; // 'p' jest zmienną wskaźnikową przechowującą adres liczby typu 'int'
double* q; // 'q' jest zmienną wskaźnikową przechowującą adres liczby typu 'double'

struct X; // deklaracja struktury
X* pp; // definicja wskaźnika na obiekt/strukturę typu X






Z książki "Borland C++ Builder" Jim Mischel, Jeff Duntemann.

[...]
Konstruktor określa sposób tworzenia egzemplarza klasy obiektu. Nie popełniaj powszechnie stosowanego błędu zakładając, że to utworzenia obiektu wystarczy po prostu zadeklarować zmienną, której typem jest klasa obiektu:

Kod: Zaznacz cały
Aclass = MyObjectInstance; //to nie będzie działać!


To nie będzie działać. Kompilator rzeczywiście wygeneruje błąd: "Klasy w stylu VCL należy budować przy użyciu operatora new", jeśli spróbujesz to zrobić (zakładają oczywiście, że Twój obiekt pochodzi od klasy TObject). Przyczyna tego jest dość złożona i niezbyt związana z naszą dyskusją. Rzecz w tym, że musisz zadeklarować wskaźnik do obiektu, tak jak w poniższym przykładzie:

Kod: Zaznacz cały
Aclass *MyObjectInstance; // to jeszcze nie wystarczy


Nie zrozum mnie źle: musisz to zrobić - jak się przekonasz na podstawie wydruku 8.8 przedstawionego w dalszej części tego rozdziału - ale zadeklarowanie wskaźnika do zmiennej klasy obiektu nie wystarczy. Obiekty mają swoją specyfikę, której jeszcze nie mogę wyjaśnić, i tworzone są w procesie dwuetapowym. Najpierw musisz zadeklarować wskaźnik do zmiennej w sposób pokazany wyżej. Następnie musisz utworzyć ten obiekt za pomocą operatora new w sposób następujący:

Kod: Zaznacz cały
MyObjectInstance = new Aclass;


new operuje na obszarze pamięci zwanym stertą, którego szczegółowo nie omówimy w tej książce. Sterta znana jest również po nazwą pamięci dynamicznej i jest tak nazywana, ponieważ kod C++ Buildera potrafi tworzyć i usuwać z niej zmienne. Istnieje jeszcze pamięć statyczna, w której tworzone są zwykłe zmienne, ale nie zmienia się ona podczas wykonywania programu i przez cały ten czas zwykłe zmienne zajmują obszar. Natomiast zmienne w pamięci dynamicznej mogą powstawać i znikać, co pozwala na bardziej efektywne wykorzystanie pamięci RAM.

- Obiekty VCL mogą istnieć tylko w pamięci dynamicznej. Operator new układa je na stercie i informuje ukrytą maszynerię C++ Buildera, która zarządza pamięcią dynamiczną, że obiekt istnieje, mówi też w którym miejscu.

[...]

Kiedy operator new umieści obiekt w pamięci, wywołuje jego konstruktora, aby mógł sam siebie zainicjować - ustawić wartości domyślne, utworzyć inne obiekty, wykonać pewne obliczenia itp. Konstruktora musimy dostarczyć dla każdej wywodzącej się od TObject klasy, którą tworzymy. A pierwszą rzeczą wykonywaną przez konstruktora - zanim wykona on cokolwiek innego - jest wywołanie konstruktora TObject.

Konstruktor klasy deklaruje się w definicji klasy w sposób następujący:

Kod: Zaznacz cały
virtual __fastcall NazwaKlasa(<parametry>);


[...]
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
    NieznanyNieznana

Re: Dynamiczny TPanel: Access Violation

Nowy postprzez wargo » niedziela, 11 października 2009, 12:55

Jakby co, problem rozwiązałem!
Avatar użytkownika
wargo
Mądrosław
Mądrosław
 
Posty: 389
Dołączył(a): niedziela, 13 lipca 2008, 16:44
PodziÄ™kowaÅ‚ : 12
OtrzymaÅ‚ podziÄ™kowaÅ„: 3
System operacyjny: Windows 7
Kompilator: C++ Builder 6 Personal
Gadu Gadu: 6259515
    NieznanyNieznana

Re: Dynamiczny TPanel: Access Violation

Nowy postprzez wargo » niedziela, 11 października 2009, 15:29

Cyfrowy Baron napisał(a):Twoje uwagi nic tutaj nie zmienią,jedyny efekt jaki wnoszą to zaśmiecanie forum.

Dlatego zamykam temat, jeśli chcecie rozmawiajcie w oddzielnym bo ten jest o czymś innym :idea:
Avatar użytkownika
wargo
Mądrosław
Mądrosław
 
Posty: 389
Dołączył(a): niedziela, 13 lipca 2008, 16:44
PodziÄ™kowaÅ‚ : 12
OtrzymaÅ‚ podziÄ™kowaÅ„: 3
System operacyjny: Windows 7
Kompilator: C++ Builder 6 Personal
Gadu Gadu: 6259515
    NieznanyNieznana


  • Podobne tematy
    Odpowiedzi
    Wyświetlone
    Ostatni post

Powrót do Ogólne problemy z programowaniem

Kto przeglÄ…da forum

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

cron