PDA

View Full Version : QHash::unite() question



aMan
2nd November 2006, 13:26
Hi,
I have the following code


QHash<Blub, Blab>* firstHash = new QHash..;
QHash<Blub, Blab>* secondHash = new QHash..;
..
firstHash->unite(*secondHash);
// delete secondHash;


When I uncomment the delete, than my application crashes. I assume it's because all elements in the secondHash are deleted and not more available in the firstHash.

Is it save to leave the second Hash undeletet? Wouldn't that be a memory leak?

sunil.thaha
2nd November 2006, 14:42
I don't get any error in the following Code


p, li { white-space: pre-wrap; } #include <iostream>
#include <QHash>



int main(){

QHash<int, int > *firstHash = new QHash<int, int >;
(*firstHash)[0] =0;
(*firstHash)[1] =1;
(*firstHash)[2] =1;
(*firstHash)[3] =2;
(*firstHash)[4] =3;



QHash<int, int > *secondHash = new QHash<int, int>;
(*secondHash)[0] =0;
(*secondHash)[2] =1;
(*secondHash)[4] =2;
(*secondHash)[6] =3;
(*secondHash)[8] =4;

firstHash->unite( *secondHash);


delete secondHash;
std::cout << " Second Deleted " << std::endl;
std::cout << " First :" << (*firstHash)[2] << std::endl;
std::cout << " First :" << (*firstHash)[6] << std::endl;
delete firstHash;
std::cout << " First Deleted " << std::endl;
return 0;
}




Now is your Blah a Blah or a Blah*
Or is the Blah class having a dataMember as pointer. if so have you made the copy construction and assisgnment operator.

jpn
2nd November 2006, 16:56
What kind of type is "Blub"? Qt's containers contain copies of values. So both containers have their own instances of Blubs. So destroying one hash does basically not affect another hash anyhow. Normally you don't need to allocate containers on the heap so they get automatically destroyed after going out of the scope..

aMan
2nd November 2006, 18:09
Thanks for the help but I think the problem is a bit more complex.

I use the QHash for a TableModel. The key is a struct which describes the position of the item in the table and the value is a QVariant. I then search the QHash in the TableModel::data() method for the value and return it.
So far, so good.
When I want to insert some columns or rows, I have to iterate over the Hash and add the count of the new columns or rows to the position. I'll attach the code for the insert method. Hopefully it's not to much..


struct ItemPosition {
ItemPosition(int p_column, int p_row) : column(p_column), row(p_row) {}
int column;
int row;
};



m_tableItems = new QHash<TabM::ItemPosition, QVariant>();


bool TableModel::insertColumns(int p_column, int p_count, const QModelIndex & p_parent) {
if (p_column > columnCount())
p_column = columnCount();
beginInsertColumns(p_parent, p_column, p_column+p_count-1);

// moving elements
QHash<TabM::ItemPosition, QVariant>* l_tempTableItems = new QHash<TabM::ItemPosition, QVariant>();
QMutableHashIterator<TabM::ItemPosition, QVariant> l_iterator(*m_tableItems);
while(l_iterator.hasNext()) {
l_iterator.next();
QVariant l_tmpVal = l_iterator.value();
TabM::ItemPosition l_tmpPos= l_iterator.key();
if(l_tmpPos.column >= p_column) {
l_tempTableItems->insert(TabM::ItemPosition(l_tmpPos.column+p_count, l_tmpPos.row), l_tmpVal);
l_iterator.remove();
}
}

// joining hashes
if (l_tempTableItems->size() < m_tableItems->size()) {
// works..
m_tableItems->unite(*l_tempTableItems);
delete l_tempTableItems;
}
else {
// causes a crash if the delete is uncommented
l_tempTableItems->unite(*m_tableItems);
// delete m_tableItems;
m_tableItems = l_tempTableItems;
}

m_columnCount+=p_count;
endInsertColumns();

//debug output
cout << "i3" << endl;
QHashIterator<TabM::ItemPosition, QVariant> l_iterator2(*m_tableItems);
while(l_iterator2.hasNext()) {
l_iterator2.next();
QVariant l_tmpVal = l_iterator2.value();
TabM::ItemPosition l_tmpPos= l_iterator2.key();
cout << "position, row: " << l_tmpPos.row << ", column: " << l_tmpPos.column << " value: ";
if(l_tmpVal.isValid()) cout << l_tmpVal.toString().toStdString() << endl;
else cout << "no val" << endl;
}
cout << "i4" << endl;
return true;
}

The program is crashing after the insert function, the "i4" is emited..

@jpn
The hash is on the heap, because of the joining and because i don't want to have the includes in the header files (faster compiling).

aMan
5th November 2006, 14:02
Does really nobody can help me?

jacek
5th November 2006, 14:45
Can we see the backtrace?

aMan
5th November 2006, 15:54
I have put the code into a function insertFields(..) that is called from insertRows(..) and insertColumns(). Here is the Backtrace..


#0 0x0804f0bb in My::TableModel::insertFields ()
#1 0x0804f4fe in My::TableModel::insertColumns ()
#2 0x0804bc57 in T2A::MainWindow::addColumn ()
#3 0x0804bf4e in T2A::MainWindow::MainWindow ()
#4 0x0804bb8d in main ()

jacek
5th November 2006, 16:04
#0 0x0804f0bb in My::TableModel::insertFields ()
#1 0x0804f4fe in My::TableModel::insertColumns ()
#2 0x0804bc57 in T2A::MainWindow::addColumn ()
#3 0x0804bf4e in T2A::MainWindow::MainWindow ()
#4 0x0804bb8d in main ()
compile your application in debug mode, so that we can see parameter values,
make it crash.

aMan
5th November 2006, 16:50
It had crashed, because it crashes right after the start and there was a seg fault (I hadn't copied the whole text, maybe a mistake..).

Here is the full (well, i cut the gdb infos) gdb output.

(gdb) run
Starting program: /home/damdam/Documents/projekte/cpp/qt/Table2ASCII/build/table2ascii
[Thread debugging using libthread_db enabled]
[New Thread -1221245264 (LWP 13707)]
Qt: gdb: -nograb added to command-line options.
Use the -dograb option to enforce grabbing.
i3
i4

Program received signal SIGSEGV, Segmentation fault.
[Switching to Thread -1221245264 (LWP 13707)]
0x0804fbbb in QHash<My::TabM::ItemPosition, QVariant>::setSharable (this=0x80a9aa8, sharable=true) at /usr/include/QtCore/qhash.h:229
229 inline void setSharable(bool sharable) { if (!sharable) detach(); d->sharable = sharable; }
(gdb) bt
#0 0x0804fbbb in QHash<My::TabM::ItemPosition, QVariant>::setSharable (this=0x80a9aa8, sharable=true) at /usr/include/QtCore/qhash.h:229
#1 0x0804fbe7 in ~QMutableHashIterator (this=0xbfd3609c) at /usr/include/QtCore/qhash.h:802
#2 0x0804ee0f in My::TableModel::insertFields (this=0x809ae08, p_field=0, p_count=1, p_orientation=Qt::Horizontal, p_parent=@0xbfd36154) at my_tablemodel.cpp:137
#3 0x0804eeb6 in My::TableModel::insertColumns (this=0x809ae08, p_column=0, p_count=1, p_parent=@0xbfd36154) at my_tablemodel.cpp:63
#4 0x0804bd61 in T2A::MainWindow::addColumn (this=0xbfd361e8) at MainWindow.cpp:47
#5 0x0804c822 in MainWindow (this=0xbfd361e8) at MainWindow.cpp:27
#6 0x0804bc87 in main (argc=Cannot access memory at address 0x0) at main.cpp:9
This is the first time i use gdb from the command line, so please apologise if I've forgotten something..

jacek
5th November 2006, 17:03
#0 0x0804fbbb in QHash<My::TabM::ItemPosition, QVariant>::setSharable (this=0x80a9aa8, sharable=true) at /usr/include/QtCore/qhash.h:229
#1 0x0804fbe7 in ~QMutableHashIterator (this=0xbfd3609c) at /usr/include/QtCore/qhash.h:802
It looks like you delete m_tableItems while QMutableHashIterator still uses it. Add curly braces around lines 8--17 to force the destruction of l_iterator.

aMan
5th November 2006, 17:57
Cool, thanks..
It works now..