Składnik statyczny w klasie i biblioteki

0

Witam.
Od jakiegoś już czasu trenuję programowanie w c++. Wymyśliłem sobie programik (do obsługi bazy MySQL z wykorzystaniem biblioteki mysql++) i próbuję go zrealizować.

Dzisiaj stworzyłem sobie klasę ze zmienną statyczną oraz funkcją statyczną, która na niej będzie wykonywać pewne operacje. (to umieściłem w pliku nagłówkowym). W pliku *.cpp umieściłem definicję funkcji oraz tej zmiennej statycznej z przypisaniem jej odpowiedniej wartości. A całość skompilowałem (oczywiście po podlinkowaniu odpowiednich bibliotek do mysql'a)
A oto pliki tej mojej pseudo biblioteki którą właśnie skompilowałem:

Plik nagłówka DataBase.h

#include <mysql++.h>
class wxConfigure;

class DataBase
    {
        static mysqlpp::Connection MYSQL_Obj;
        wxConfigure * Config;

        public:
            DataBase(){};
            ~DataBase(){};

           // Połączenie z MySQL
            static int Connect();
    };
Plik DataBase.cpp

mysqlpp::Connection DataBase::MYSQL_Obj(false);

int DataBase::Connect()
{

}

No i wygląda na to że wszystko jest ok ale niestety...

Postanowiłem podlinkować tą moją bibliotekę do innego projektu napisanego przy użyciu wxWidgets. Dodałem więc tam plik nagłówkowy, linkerowi dałem namiary na potrzebne pliki z bibliotekami, strorzylem w końcu zmienną globalną mojego własnego typu "DataBase".

I jakie było moje zdziwienie kiedy to program wykrzaczył się (zwracał SIGSEGV) w momencie zamykania programu. Spróbowałem jeszcze raz go odpalić tym razem uruchamiając dla tego obiektu funkcję DataBase::Connect(); i o dziwo wtedy program wyłącza się normalnie. Próbowałem jeszcze wiele razy i za każdym razem było tak samo. Gdy obiekt database tylko sobie zdefiniowałem i nic na nim nie robiłem to przy wyłączaniu programu zawsze się wykrzacza, gdy uruchomię funkcję to wtedy nie. Bez tej nieszczęsnej definicji program działa normalnie (zresztą nie ma tam nie wiadomo jakich udziwnień... czysty projekt uruchamiający okienko aplikacji i nic poza tym).

Czy ktoś wie co może być przyczyną? Ew. jak zrobić by się dowiedzieć?

A i jeszcze drugie pytanie. Czy kolejność dyrektyw "include" ma znaczenie? :P

Jeśli piszę:

    #include <wx/string.h>
    #include <mysql++.h>

to ta moja biblioteczka kompiluje się normalnie a jeśli:

    #include <mysql++.h>
    #include <wx/string.h>

to kompilator zwraca błąd że nie można zamienić TCHAR* na WCHAR*

Z góry dzięki za wszystkie odpowiedzi. Pozdrawiam.

0

@pierwsze
najprawdopodobniej, w momencie wywolywania Connect z dll, cos jest inicjalizowane, zas w momencie konczenia programu i wyladowywania dllki - cos jest obowiazkowo deinicjalizowane z optymistycznym zalozeniem ze np. wskanziki sa poprawne i/lub niepuste itd. zbadaj co sie dzieje w momencie konczenia programu - jakie destruktory pochodzace z dll sa odpalne itp, i postaraj sie aby to na czym operuja bylo zawsze zainicjowane, nie wazne czy odpalisz Connect() czy nie

@drugie
ktoras z nich jest zle napisana bo zaklada cos czego nie powinna, i/lub masz spalone ustawienie wyboru trybu kompilacji (unicode/mbsz)

0

@drugie
Hmm... czyli pewnie "MySQL++" szwankuje bo wxWidgets jest bardzo dobrze napisaną biblioteką. Wszystkie DLLki są skompilowane z parametrem Unicode, oraz kompilacja też jest na to kodowanie ustawiona.

@pierwsze
Wiesz... najdziwniejsze jest to że ten Connect() który odpalam jest moją własną funkcją statyczną w mojej klasie i ciało tej funkcji jest zupełnie puste. I jak ją odpalę to działa ok, a jak nie odpalę to wtedy krzaki i SIGSEGV

0

btw. sigsegv vs TCHAR/WCHAR - to w koncu linux czy windows?

0

Windows...
TCHAR/WCHAR - to mi zwraca w momencie kompilacji kiedy odwrócę kolejnością dyrektywy preprocesora
sigsegv - to dostaje gdy uruchamiam program w trybie debugera żeby sprawdzić co powoduje błąd... przy jego wyłączaniu.

Używam Code::BLocks IDE :P i kompilatowa MinGW

0

Prawdopodobnie problem to "static (de)initializtion order fiasco".
Biblioteka mysql posiada jakiś składnik statyczny umożliwiający działanie całej biblioteki, moduł główny który np. ładuje na starcie i zwalnia przy końcu jakieś dll'ki czy inne zasoby.
Załóżmy że obiekt typu "mysqlpp::Connection" podczas konstrukcji oraz destrukcji korzysta z ów statycznego modułu głównego.
Teraz deklarując statyczną zmienną "MYSQL_Obj" pojawia się problem - który obiekt (statyczny moduł główny, czy zmienna "MYSQL_Obj") będzie wcześniej tworzony/niszczony. Jeśli "MYSQL_Obj" będzie tworzony wcześniej niż moduł główny to jest kłopot. Jeśli "MYSQL_Obj" będzie zniszczony później niż moduł - też jest kłopot.
Tobie trafił się akurat przypadek drugi - "MYSQL_Obj" był niszczony już po zniszczeniu modułu głównego, a destruktor chciał z niego skorzystać. pÓÓÓÓki nie korzystałeś z klasy "DataBase" kompilator nie tworzył zmiennej "MYSQL_Obj" dlatego dopiero wywołanie jakiejkolwiek metody (nawet nic nie robiącej) ujawniło problem.
Konsekwencją jest niemożność deklarowania zmiennych statycznych typu "mysqlpp::Connection" i prawdopodobnie wielu innych z biblioteki mysql.

Rozwiązaniem jest pewne obejście wyjaśnione tutaj:
http://www.parashift.com/c++-faq-lite/ctors.html#faq-10.12

0

o super :) Bardzo cenna informacja :)

Dziękuje i pozdrawiam ;)

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