PDA

View Full Version : (Another) segmentation fault



Lebowski
3rd April 2006, 13:08
Hello.

I've started using QT recently and I quite like it so far. However I can't get past this error.

In Povezava.ui.h I have setup connection to database like this:


void Povezava::Connect_clicked()
{
int indeks = tipbaze->currentItem();
if (indeks==0) {driver ="QMYSQL3";}
if (indeks==1) {driver ="QPSQL7";}
if (indeks==2) {driver ="QODBC3";}

QSqlDatabase *baza = QSqlDatabase::addDatabase ( driver );
baza->setHostName ( hostm );
baza->setDatabaseName ( namem );
baza->setUserName ( userm );
baza->setPassword ( passm );

bool ok = baza->open();
}
This part definitelly works as I've tested it in many ways.

In another form I'm checking if the connection is properly opened with this code:

void GlavnoO :: pushButton3_clicked()
{
bool ok = FALSE;
ok = povezava.baza->isOpen();
}
I don't get any errors when compiling. But whet I click on this button I get segmentation fault EVERY time! I've tried it with connection opened and closed. I also did 'make clean' just in case. Nothing worked.

I have no idea how to get past this.

zlatko
3rd April 2006, 13:14
Its ok becouse you declare baza variable in method Connect_clicked(). After returning from this method you havent access to this variable. For solving you need declare baza as class member

Lebowski
3rd April 2006, 13:24
I already have baza declared as class member in povezava.ui.h

It's under povezava.ui.h->members->class variables->public-> QSqlDatabase *baza ;

zlatko
3rd April 2006, 13:57
So why you redeclare it in


QSqlDatabase *baza = QSqlDatabase::addDatabase ( driver );


Right code



baza = QSqlDatabase::addDatabase ( driver )

Lebowski
3rd April 2006, 14:10
Tried that but still getting segmentation fault in the same way :(

jacek
3rd April 2006, 17:18
Compile your application in debug mode and run it from a debugger. When it crashes, print the stack trace and post it here.

Lebowski
4th April 2006, 06:49
I've added "CONFIG += debug" into my project file but the output when my application crashes still says only "Segmentation fault".

This is debug from 'make':

[root@simon dbconn]# make --debug
GNU Make 3.80
Copyright (C) 2002 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.
There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A
PARTICULAR PURPOSE.
Reading makefiles...
Updating goal targets....
File `first' does not exist.
File `all' does not exist.
Prerequisite `povezava.ui.h' is newer than target `.ui/povezava.cpp'.
Must remake target `.ui/povezava.cpp'.
/usr/lib/qt-3.3/bin/uic povezava.ui -i povezava.h -o .ui/povezava.cpp
Successfully remade target file `.ui/povezava.cpp'.
Prerequisite `.ui/povezava.cpp' is newer than target `.obj/povezava.o'.
Prerequisite `povezava.ui.h' is newer than target `.obj/povezava.o'.
Must remake target `.obj/povezava.o'.
g++ -c -pipe -Wall -W -g -DQT_SHARED -DQT_NO_DEBUG -DQT_THREAD_SUPPORT -I/usr/lib/qt-3.3/mkspecs/default -I. -I/usr/lib/qt-3.3/include -I.ui/ -I. -I.moc/ -o .obj/povezava.o .ui/povezava.cpp
/usr/lib/qt-3.3/include/qsqldatabase.h:63: warning: ‘class QSqlDriverCreatorBase’ has virtual functions but non-virtual destructor
/usr/lib/qt-3.3/include/qtooltip.h:86: warning: ‘class QToolTip’ has virtual functions but non-virtual destructor
Successfully remade target file `.obj/povezava.o'.
Prerequisite `.obj/povezava.o' is newer than target `povezava'.
Must remake target `povezava'.
g++ -o povezava .obj/main.o .obj/glavnoo.o .obj/povezava.o .obj/moc_glavnoo.o .obj/moc_povezava.o -L/usr/lib/qt-3.3/lib -L/usr/X11R6/lib -lqt-mt -lXext -lX11 -lm
Successfully remade target file `povezava'.
Must remake target `all'.
Successfully remade target file `all'.
Must remake target `first'.
Successfully remade target file `first'.
[root@simon dbconn]# ./povezava
Segmentation fault

SkripT
4th April 2006, 11:20
Just a way to "debug", check everytime before accesing to baza pointer if its null and show a message on screen or on the standard output, for example, in this case.

wysota
4th April 2006, 11:41
Try this:

$ gdb ./povezava
(gdb) run
(some output will go there and eventually the application will segfault)
(gdb) bt


and show us the result of "bt".

Lebowski
4th April 2006, 12:03
Here is what I get with gdb:

(gdb) run
Starting program: /home/simon/projects/dbconn/povezava
Reading symbols from shared object read from target memory...done.
Loaded system supplied DSO at 0xb9e000
[Thread debugging using libthread_db enabled]
[New Thread -1208837664 (LWP 9818)]

Program received signal SIGSEGV, Segmentation fault.
[Switching to Thread -1208837664 (LWP 9818)]
0x04d45bb5 in QSqlDatabase::isOpen (this=0xffff) at sql/qsqldatabase.cpp:772
772 return d->driver->isOpen();
(gdb) bt
#0 0x04d45bb5 in QSqlDatabase::isOpen (this=0xffff) at sql/qsqldatabase.cpp:772
#1 0x0804bcb0 in GlavnoO::test_clicked (this=0xbff491fc) at .ui/../glavnoo.ui.h:28
#2 0x0804e877 in GlavnoO::qt_invoke (this=0xbff491fc, _id=52, _o=0xbff48af8) at .moc/moc_glavnoo.cpp:87
#3 0x04ab9eb4 in QObject::activate_signal (this=0x9967440, clist=0x9969488, o=0xbff48af8) at kernel/qobject.cpp:2355
#4 0x04aba374 in QObject::activate_signal (this=0x9967440, signal=4) at kernel/qobject.cpp:2324
#5 0x04e39c7e in QButton::clicked (this=0xffff) at .moc/release-shared-mt/moc_qbutton.cpp:152
#6 0x04b59a63 in QButton::mouseReleaseEvent (this=0x9967440, e=0xbff48e54) at widgets/qbutton.cpp:836
#7 0x04af8187 in QWidget::event (this=0x9967440, e=0xbff48e54) at kernel/qwidget.cpp:4699
#8 0x04a550dd in QApplication::internalNotify (this=0xffff, receiver=0x9967440, e=0xbff48e54) at kernel/qapplication.cpp:2635
#9 0x04a5603f in QApplication::notify (this=0xbff49334, receiver=0x9967440, e=0xbff48e54) at kernel/qapplication.cpp:2421
#10 0x049ec746 in QETWidget::translateMouseEvent (this=0x9967440, event=0xbff49118) at kernel/qapplication.h:518
#11 0x049eaf01 in QApplication::x11ProcessEvent (this=0xbff49334, event=0xbff49118) at kernel/qapplication_x11.cpp:3468
#12 0x049ff008 in QEventLoop::processEvents (this=0x9944fe0, flags=Variable "flags" is not available.
) at kernel/qeventloop_x11.cpp:192
#13 0x04a6d82b in QEventLoop::enterLoop (this=0x9944fe0) at kernel/qeventloop.cpp:198
#14 0x04a6d736 in QEventLoop::exec (this=0x9944fe0) at kernel/qeventloop.cpp:145
#15 0x04a54aa9 in QApplication::exec (this=0xbff49334) at kernel/qapplication.cpp:2758
#16 0x0804bc31 in main (argc=1, argv=0xbff49414) at main.cpp:19
(gdb) Quit
(gdb)

wysota
4th April 2006, 13:21
Can we see the current code too?

Lebowski
4th April 2006, 13:32
Code is still the same as it was in the first post.

wysota
4th April 2006, 13:37
Then this code is surely invalid as you have a local variable "baza" which points to the database and a member variable "baza" which points to some garbage which probably causes a crash.

Lebowski
4th April 2006, 13:45
Possible. But why doesn't compiler find any errors? And how do i change the code to make it work?

wysota
4th April 2006, 13:49
Why should it find errors? The code is valid C++, it just doesn't do what you wnt. Zlatko already told you how to correct it.

Lebowski
4th April 2006, 13:54
You mean this post?

So why you redeclare it in


QSqlDatabase *baza = QSqlDatabase::addDatabase ( driver );


Right code



baza = QSqlDatabase::addDatabase ( driver )

I tried that but I'm still getting segmentation fault.

wysota
4th April 2006, 13:58
But the code is different. Run it under debugger again. And please paste the contents of test_clicked() slot.

Lebowski
4th April 2006, 14:00
Hmm, I think I figured out my problem with help from all of you. I need to properly specify 'QSqlDatabase *baza; ' as a global variable. Now the n00b question: how do I do that, please? Tried to do it in my main.cpp but it doesn't work.

wysota
4th April 2006, 14:06
No, you don't have to do that. First of all QSqlDatabase::addDatabase() returns an object and not a pointer. And second of all you can access the database later on by calling QSqlDatabase::database(). You don't need a variable to hold that handler. Please read the reference of QSqlDatabase. It's explained there (on the very beginning of the detailed description).

Lebowski
5th April 2006, 05:55
Following that example I changed


1.
void GlavnoO :: pushButton3_clicked()
{
bool ok = FALSE;
ok = povezava.baza->isOpen();
}

to

void GlavnoO::pushButton3_clicked()
{
bool ok = FALSE;
QSqlDatabase *baza = QSqlDatabase::database();
ok = baza->isOpen();
}
It compiles normally but it crashes with segmentation fault again when I press that button.

And I have to use pointers cause I have this in my Qt Assistant QSqlDatabase Reference:


Static Public Members
QSqlDatabase * addDatabase ( const QString & type, const QString & connectionName = defaultConnection )
QSqlDatabase * addDatabase ( QSqlDriver * driver, const QString & connectionName = defaultConnection )
QSqlDatabase * database ( const QString & connectionName = defaultConnection, bool open = TRUE )
void removeDatabase ( const QString & connectionName )
void removeDatabase ( QSqlDatabase * db )
bool contains ( const QString & connectionName = defaultConnection )
QStringList drivers ()
void registerSqlDriver ( const QString & name, const QSqlDriverCreatorBase * creator )
bool isDriverAvailable ( const QString & name )

jpn
5th April 2006, 07:43
Notice also the sentence in docs:


If connectionName does not exist in the list of databases, 0 is returned.

So add a check for null pointer:


void GlavnoO::pushButton3_clicked()
{
bool ok = FALSE;
QSqlDatabase *baza = QSqlDatabase::database();
if (baza)
{
ok = baza->isOpen();
}
}

Lebowski
5th April 2006, 07:50
Yep, that solves the segmentation fault. But I would still like to know how to acces databse connection which I opened in another form.

wysota
5th April 2006, 07:56
And I have to use pointers

Sure, you're using Qt3 and I was looking at Qt4 docs.


But I would still like to know how to acces databse connection which I opened in another form.

First check if addDatabase returns a valid database handle.

Lebowski
5th April 2006, 08:06
I did check with this code in form povezava (povezava.ui.h):

bool ok = baza->open();
if (!ok) {QMessageBox::warning (this, "Pozor!!!!!!!!!!!", "not working",1,0,0);}
else {
QMessageBox::information ( this, "Uspeh!!!!!!!!!", "working",1,0,0 );
close();
};
And it certainly works.

But now I need to access it from a different form, from file glavnoo.ui.h.

wysota
5th April 2006, 08:09
So why don't you use QSqlDatabase::database()?

Lebowski
5th April 2006, 08:11
I am using that.

void GlavnoO::test_clicked()
{
bool ok = FALSE;
QSqlDatabase *baza = QSqlDatabase::database();
if (baza) {
ok = baza->isOpen();
};
Originally it was without 'if (baza) ...' statement.

wysota
5th April 2006, 08:37
So what's wrong with that? The form you use it in doesn't matter. You can use QSqlDatabase::database() from anywhere. Just makesure addDatabase() has been invoked earlier.

Lebowski
6th April 2006, 06:33
Yep, it does work now!! Thanx all. :)

Seems I was missing QSqlDatabase::database() statement so my 'baza' pointer had a random value.