szokujący błąd

0

witam,

korzystam z Dev-C++ 4.9.9.2 i podczas dzialania programu nagle zaczelo mi wywalac bledy. Po zbadaniu okazalo sie ze wartosc wskaznika jakby jest gdzies w programie zerowana. Pisze jakby dlatego ze po sprawdzeniu w programie:

if (myClass.wsk == 0)
MessageBox(NULL, "blad", "blad", MB_OK) ;

wyskakuje mi okienko. Ale jak sobie obserwuje zmienna w oknie debugera to widac ze ma jednak jakas wartosc i zerowa nie jest!
Jak sobie zatrzymam program przed ta instrukcja sprawdzajaca, widze w oknie debugera ze zmienna ma wartosc np. 0x3e3f98 i zmodyfikuje ta wartosc na taka sama tzn wybiore sobie okienko "modyfikuj wartosc" i wcisne OK (nic nie zmieniajac bo jest poprawna) to wtedy wszystko jest w porzadku.

Co ciekawe zachowuje sobie codziennie poprzednie wersje i po rozpakowaniu wczesniejszych exeki dzialaja poprawnie ale jak je ponownie skompiluje to wychodzi ten sam blad.

glowie sie nad tym od dwoch dni i jestem w kropce.
w tej chwili obiekt myClass jest tworzony jeden na caly program a robie to tak:

w pliku main.h

class MyClass 
{
  public:
    WSK* wsk ;
} ;

extern MyClass myClass ;

w pliku main.cpp

#include "main.h"

MyClass myClass ;

...

jakis innyplik.h

#include "innyplik.h"

class InnaKlasa
{
  void funkcja() ;
} ;

innyplik.cpp

void InnaKlasa::funkcja()
{
  // i tu jak sprawdze 
  // to sie okazuje ze jest zero a debuger pokazuje co innego
  if (myClass.wsk == 0) {}
}

Dodam jeszcze ze jak sobie na nowo utworze projekt taki jak powyzej wypisalem to wszystko gra tylko w tym cos sie spieprzylo (mam w nim obecnie kilkaset plikow). Instalowalem tez poprzednie wersje Dev-C++ i ten sam blad.

Co o tym sadzicie? Co moge zrobic w takiej sytuacji?

0

gdzie masz taki kodzik
wsk = new WSK;
??

0
Milka napisał(a)

gdzie masz taki kodzik
wsk = new WSK;
??

Milka,
o przepraszam, nie napisalem tego w tym kodzie ale chodzilo mi o ukazanie idei

wskaznik w kodzie mojego programu wskazuje na jakis dobry obszar pamieci - new jest na pewno wywolywane, wszystko to sprawdzilem :)

co ciekawe jesli sprawdze w pliku main.cpp

if (myClass.wsk == 0)
  MessageBox(NULL, "blad", "blad", MB_OK) ;

to widac ze wszystko jest ok, problem pojawia sie przy odwolywaniu sie do tego wskaznika przez myClass w innych plikach

0

Hmmm... Błąd zapewne szokujący ale Twój... samo się nic nie dzieje.
Zapodaj może konstruktor tego MyClass.
Albo najpierw dopisz do konstruktora domyślnego MyClass coś co pokaże/wydrukuje informację o wywołaniu kontruktora na ekranie, np.:

MyClass::MyClass()
{
    cout << "[MyClass ctor]" << endl;
    // ....
}

i zobacz czy na pewno jeden obiekt jest :>

0
marcinEc napisał(a)

Hmmm... Błąd zapewne szokujący ale Twój... samo się nic nie dzieje.
Zapodaj może konstruktor tego MyClass.
Albo najpierw dopisz do konstruktora domyślnego MyClass coś co pokaże/wydrukuje informację o wywołaniu kontruktora na ekranie, np.:

MyClass::MyClass()
{
    cout << "[MyClass ctor]" << endl;
    // ....
}

i zobacz czy na pewno jeden obiekt jest :>

Panie i Panowie

jeszcze raz pisze, ze wszystko jest tworzone poprawnie sa wywolywane konstruktory, sa tworzne odpowiednie obiekty

WSK* wsk ; 

WSK to tez klasa i w kodzie ktory znajduje sie w pliku main.cpp moge wywolywac metody tej klasy np. myClass.wsk->WykonajFunkcje() ;
dlatego ze ten wskaznik jest poprawny, natomiast w innych plikach takie wywolanie nie dziala bo myClass.wsk jest rowne 0, wiec przy wywolaniu myClass.wsk->WykonajFunkcje() ; wywala blad

0

Jeśli jest 0 w innych plikach to znaczy, że jednak nie jest dobrze tworzony :-P

  1. Dopisz informację o tworzeniu do konstruktora (czy lepiej nawet do wszystkich konstruktorów) i zobacz ile obiektów zostanie utworzonych. To na początek, żeby wyeliminować możliwość, że coś schrzaniłeś z tworzeniem obiektów...
  2. Jesteś pewien, że wskaźnik jest zaincjalizowany poprawną wartością PRZED użyciem w innych plikach? No skądś to 0 się bierze... Twój obiekt jest globalny, no więc co robi domyślny kontruktor? Masz go w ogóle?
0
marcinEc napisał(a)

Jeśli jest 0 w innych plikach to znaczy, że jednak nie jest dobrze tworzony :-P

  1. Dopisz informację o tworzeniu do konstruktora (czy lepiej nawet do wszystkich konstruktorów) i zobacz ile obiektów zostanie utworzonych. To na początek, żeby wyeliminować możliwość, że coś schrzaniłeś z tworzeniem obiektów...
  2. Jesteś pewien, że wskaźnik jest zaincjalizowany poprawną wartością PRZED użyciem w innych plikach? No skądś to 0 się bierze... Twój obiekt jest globalny, no więc co robi domyślny kontruktor? Masz go w ogóle?

taa, jak juz mowilem wszystko jest tworzone poprawnie
w konstruktorze MyClass zeruje wsk
MyClass::MyClass()
{
wsk = NULL ;
}

wsk jest tworzony podczas startu programu
wsk = new WSK ;

jest on poprawnie tworzony . .. wszystkie funkcje tego obiektu moge wywolywac bez problemu ale tylko w pliku main.cpp, skoro je moge wywolywac to wszystko jest poprawnie tworzone, program sie uruchamia, dziala. W momencie wykonywania kodu ktory byl zapisany w innych plikach niz main.cpp okazuje sie ze wskaznik ten jest rowny zero
no i jeszcze gdyby debuger mi pokazywal ze jest zero to by wszystko bylo ok, ale pokazuje poprawna wartosc :)

dla pewnosci sprawdzilem przed chwila, obiekt myClass jak i wsk jest tworzony tylko jeden raz w programie

wszystko to jest dosc dziwne bo jak juz napisalem wczesniej poprzednie wersje ktore normalnie sie kompilowaly i dzialaly naraz maja ten sam problem

program jest oczywiscie caly przebudowywany.
przypuszczam ze jest to niestety wina Dev-c++ :|

0

Hmmm.. To nie ma prawa źle działać jeśli program jest dobrze napisany (tzn. odwołania do globalnej zmiennej)... To, że działał wcześniej NIE oznacza, że był dobrze napisany ale być może zmieniłeś coś, nie bierzesz jakiegoś drobiazgu pod uwagę?
Nikt tu niestety nie ogarnie wszystkiego na odległość, stąd te pytania i propozycje...

Nie sądze żeby był to błąd kompilatora/debugera [btw. kompilatorem jest np. MinGW, a nie Dev-C++].

np. taki program działa poprawnie mimo, że jest źle napisany (brak alokacji):

class AA
{
public:
      void foo();
};
void AA::foo()
{
     cout<<"AA::foo()" << endl;
}
int main(int argc, char *argv[])
{
    AA *paa = 0; // na chama NULL, a co :)
    paa->foo();
}

Ale już taka klasa spowoduje błąd:

class AA
{
      int m_a;
public:
      void foo();
};
void AA::foo()
{
     cout<<"AA::foo()" << m_a << endl;
}

Podobnie może być u Ciebie i przypadkiem odkryłeś, że wsk ma wartość 0 (?) Co do pokazywania wartości w debugerze, to trzeba uważać co tak naprawdę pokazuje, np. czy to zmienna lokalna czy globalna o takiej samej nazwie.

0

To, ze wywolujesz new na starcie programu (main) wcale nie oznacza, ze wskaznik jest zainicjowany przed pierwszym wywolaniem jakiejs funkcji.

Przypuszczam, ze robisz cos takiego:

  • w konstruktorze klasy z tym feralnym wskaznikiem zerujesz wskaznik
  • w jakiejs funkcji w INNYM PLIKU (np. a.cpp) ustawiasz ten wskaznik poprzez np. wywolanie new.
  • w INNYM PLIKU niz a.cpp (np. b.cpp, ktory moze ale nie musi zawierac tez definicje tej feralnej klasy) masz zdefiniowany obiekt globalny tej klasy czyli linijka "MyClass myClass".

Takie postepowanie jest bledne i czasem moze, ale na ogol nie bedzie dzialac. Przed wywolaniem main sa inicjowane wszystkie obiekty globalne poprzez wywolanie ich konstruktorow. Kolejnosc wywolywania nie jest zdefiniowana dla obiektow z roznych jedn. translacji (tj. plikow cpp), natomiast dla jednego pliku cpp inicjowane sa po kolei. Jesli masz kod, ktory ustawia wskaznik, ale pechowo robi to PRZED zainicjowaniem obiektu globalnego, to masz pecha - konstruktor obiektu zaraz potem wyzeruje Ci ten wskaznik. Czasem zdarza sie oczywiscie (to zalezy od kaprysow Twojego linkera), ze kolejnosc inicjacji bedzie inna i program bedzie chodzil dobrze, tj. konstruktor feralnej klasy wywola sie najpierw, a pozniej ta funkcja, ktora ustawia wskaznik. Wtedy program bedzie Ci przez przypadek chodzil dobrze.

Przerzuc wszystkie obiekty globalne do jednego pliku cpp i ustal odpowiednia kolejnosc inicjacji, albo tak przeprojektuj program, aby zaden konstruktor nie mieszal nic na innych klasach procz swojej. To drugie rozw. jest trudniejsze, ale bardziej eleganckie.

Jesli to nie jest ten przypadek, to albo masz skielbaszony kompilator (male szanse), albo cos robisz zle, czego nam nie powiedziales.

0
Krolik napisał(a)

To, ze wywolujesz new na starcie programu (main) wcale nie oznacza, ze wskaznik jest zainicjowany przed pierwszym wywolaniem jakiejs funkcji.

Przypuszczam, ze robisz cos takiego:

  • w konstruktorze klasy z tym feralnym wskaznikiem zerujesz wskaznik
  • w jakiejs funkcji w INNYM PLIKU (np. a.cpp) ustawiasz ten wskaznik poprzez np. wywolanie new.
  • w INNYM PLIKU niz a.cpp (np. b.cpp, ktory moze ale nie musi zawierac tez definicje tej feralnej klasy) masz zdefiniowany obiekt globalny tej klasy czyli linijka "MyClass myClass".

Takie postepowanie jest bledne i czasem moze, ale na ogol nie bedzie dzialac. Przed wywolaniem main sa inicjowane wszystkie obiekty globalne poprzez wywolanie ich konstruktorow. Kolejnosc wywolywania nie jest zdefiniowana dla obiektow z roznych jedn. translacji (tj. plikow cpp), natomiast dla jednego pliku cpp inicjowane sa po kolei. Jesli masz kod, ktory ustawia wskaznik, ale pechowo robi to PRZED zainicjowaniem obiektu globalnego, to masz pecha - konstruktor obiektu zaraz potem wyzeruje Ci ten wskaznik. Czasem zdarza sie oczywiscie (to zalezy od kaprysow Twojego linkera), ze kolejnosc inicjacji bedzie inna i program bedzie chodzil dobrze, tj. konstruktor feralnej klasy wywola sie najpierw, a pozniej ta funkcja, ktora ustawia wskaznik. Wtedy program bedzie Ci przez przypadek chodzil dobrze.

Przerzuc wszystkie obiekty globalne do jednego pliku cpp i ustal odpowiednia kolejnosc inicjacji, albo tak przeprojektuj program, aby zaden konstruktor nie mieszal nic na innych klasach procz swojej. To drugie rozw. jest trudniejsze, ale bardziej eleganckie.

Jesli to nie jest ten przypadek, to albo masz skielbaszony kompilator (male szanse), albo cos robisz zle, czego nam nie powiedziales.

wskaznik w klasie myClass nie jest inicjowany przed wywolaniem funkcji main()
jest on inicjowany w czasie dzialania programu dlatego pisalem ze wszystko jest inicjowane poprawnie, jest on na sto procent poprawny

w koncu dziala jak nalezy ale nadal nie jest dla mnie jasne dlaczego dzialalo zle
zamienilem po prostu kolejnosc deklaracji w klasie z takiego jakie mialem:

MyClass myClass
{
  public:
    void fun1() ;
    void fun2() ;

    WSK* wsk ;
} ;

na:

MyClass myClass
{
  public:
    WSK* wsk ;

    void fun1() ;
    void fun2() ;
} ;

to mi przyszlo w akcie desperacji do glowy i dziala
ale dlaczego to nie wiem . . .

jeszcze z troche innej beczki
Czy mozna w Dev-C++ wlaczyc poziomy ostrzezen o bledach tak jak to jest w Visual C++?
jak w Visualu zapomne w funkcji zwrocic jakiejs wartosci to on mnie o tym informuje a w Dev-C++ tego niestety nie zauwazylem :) + cala masa innych przydatnych ostrzezen

0

powinno byc: :| sorry ale ostatnio malo spie :|

class MyClass
{
  public:
    void fun1() ;
    void fun2() ;

    WSK* wsk ;
} ;

na:

class MyClass
{
  public:
    WSK* wsk ;

    void fun1() ;
    void fun2() ;
} ;

// yyy? nie poprawiłeś się... chyba miała być odwrotna kolejność? - Q

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