diff options
| author | 2010-01-11 04:03:07 +0000 | |
|---|---|---|
| committer | 2010-01-11 04:03:07 +0000 | |
| commit | a8e52442636bb66adfdf604b0097fa525621c27f (patch) | |
| tree | 9037b34a76dccc00963412d782da156f63939a7b | |
| parent | quick fix (diff) | |
| download | KVIrc-a8e52442636bb66adfdf604b0097fa525621c27f.tar.gz KVIrc-a8e52442636bb66adfdf604b0097fa525621c27f.tar.bz2 KVIrc-a8e52442636bb66adfdf604b0097fa525621c27f.zip | |
Fixed a crash on exit after using the alias editor. Bad vtable.
git-svn-id: https://svn.kvirc.de/svn/trunk/kvirc@3831 17fca916-40b9-46aa-a4ea-0a15b648b75c
| -rw-r--r-- | src/kvilib/core/kvi_pointerhashtable.h | 10 | ||||
| -rw-r--r-- | src/kvirc/kvs/kvi_kvs_aliasmanager.cpp | 37 | ||||
| -rw-r--r-- | src/kvirc/kvs/kvi_kvs_aliasmanager.h | 11 | ||||
| -rw-r--r-- | src/modules/aliaseditor/aliaseditor.cpp | 49 |
4 files changed, 73 insertions, 34 deletions
diff --git a/src/kvilib/core/kvi_pointerhashtable.h b/src/kvilib/core/kvi_pointerhashtable.h index 4d30257d9..b5e611d10 100644 --- a/src/kvilib/core/kvi_pointerhashtable.h +++ b/src/kvilib/core/kvi_pointerhashtable.h @@ -410,7 +410,8 @@ public: { if(!pData)return; unsigned int uEntry = kvi_hash_hash(hKey,m_bCaseSensitive) % m_uSize; - if(!m_pDataArray[uEntry])m_pDataArray[uEntry] = new KviPointerList<KviPointerHashTableEntry<Key,T> >(true); + if(!m_pDataArray[uEntry]) + m_pDataArray[uEntry] = new KviPointerList<KviPointerHashTableEntry<Key,T> >(true); for(KviPointerHashTableEntry<Key,T> * e = m_pDataArray[uEntry]->first();e;e = m_pDataArray[uEntry]->next()) { if(kvi_hash_key_equal(e->hKey,hKey,m_bCaseSensitive)) @@ -421,7 +422,8 @@ public: kvi_hash_key_destroy(e->hKey,m_bDeepCopyKeys); kvi_hash_key_copy(hKey,e->hKey,m_bDeepCopyKeys); } - if(m_bAutoDelete)delete e->pData; + if(m_bAutoDelete) + delete e->pData; e->pData = pData; return; } @@ -536,8 +538,10 @@ public: if(m_bAutoDelete) delete ((T *)(e->pData)); } - delete m_pDataArray[i]; + KviPointerList<KviPointerHashTableEntry<Key,T> > * pList = m_pDataArray[i]; + //delete m_pDataArray[i]; m_pDataArray[i] = 0; + delete pList; } } m_uCount = 0; diff --git a/src/kvirc/kvs/kvi_kvs_aliasmanager.cpp b/src/kvirc/kvs/kvi_kvs_aliasmanager.cpp index 2f4f5e5d6..5256f7afd 100644 --- a/src/kvirc/kvs/kvi_kvs_aliasmanager.cpp +++ b/src/kvirc/kvs/kvi_kvs_aliasmanager.cpp @@ -39,6 +39,7 @@ KviKvsAliasManager::KviKvsAliasManager() KviKvsAliasManager::~KviKvsAliasManager() { delete m_pAliasDict; + m_pAliasManager = 0; } void KviKvsAliasManager::init() @@ -61,6 +62,42 @@ void KviKvsAliasManager::done() delete KviKvsAliasManager::instance(); } +void KviKvsAliasManager::add(const QString &szName,KviKvsScript * pAlias) +{ + // This piece of code, when inlined by gcc (i.e, placed in a header), + // shows an interesting problem. + + // KviKvsPointerHashTable<>::replace() is a template and is likely to be inlined too. + // The internals of replace() use another template called KviKvsPointerHashTableEntry<>. + // When this function is called from a dynamically loaded shared library + // the internal template is likely to be instantiated in the shared library itself. + // Now if the shared library is unloaded, a dangling vtable pointer is stored + // in the inner template and it will die once we attempt to clear the m_pAliasDict ht. + // + // This happens for KviAliasEditor, for instance. In it's commit() function + // it called this method and caused the vtable pointer to be 0x7fffdfab0030. + // + // (gdb) info symbol 0x7fffdfab0030 + // vtable for KviPointerList<KviPointerHashTableEntry<QString, KviKvsScript> > + 16 in section .data.rel.ro + // of /usr/local/lib/kvirc/4.0/modules/libkvialiaseditor.so <-- inside the module + // + // while the correct vtable (the one that appears when the add() function is called from somewhere else) is + // + //(gdb) info symbol 0x6bc210 + // vtable for KviPointerList<KviPointerHashTableEntry<QString, KviKvsScript> > + 16 in section .rodata + // of /usr/local/bin/kvirc <-- inside the executable + // + // This is a linkage problem. Either caused by gcc itself, or maybe wrong flags + // passed by the cmake generated Makefiles. Gcc should notice that the symbol is already defined + // inside the executable and use that one instead. + // + // So finally, we can't inline this. + + // The bad news is that this problem may pop up also in other pieces of code... + m_pAliasDict->replace(szName,pAlias); + emit aliasRefresh(szName); +} + void KviKvsAliasManager::completeCommand(const QString &word,KviPointerList<QString> * matches) { KviPointerHashTableIterator<QString,KviKvsScript> it(*m_pAliasDict); diff --git a/src/kvirc/kvs/kvi_kvs_aliasmanager.h b/src/kvirc/kvs/kvi_kvs_aliasmanager.h index 3db9545ed..ee142d272 100644 --- a/src/kvirc/kvs/kvi_kvs_aliasmanager.h +++ b/src/kvirc/kvs/kvi_kvs_aliasmanager.h @@ -50,11 +50,7 @@ public: KviPointerHashTable<QString,KviKvsScript> * aliasDict(){ return m_pAliasDict; }; const KviKvsScript * lookup(const QString & szName) { return m_pAliasDict->find(szName); }; - void add(const QString &szName,KviKvsScript * pAlias) - { - m_pAliasDict->replace(szName,pAlias); - emit aliasRefresh(szName); - }; + void add(const QString &szName,KviKvsScript * pAlias); bool remove(const QString & szName) { return m_pAliasDict->remove(szName); }; void clear() @@ -64,10 +60,9 @@ public: void load(const QString & filename); void completeCommand(const QString &word,KviPointerList<QString> * matches); - signals: +signals: - - void aliasRefresh(const QString &); + void aliasRefresh(const QString &); }; // namespaces are handled completly in the editing! #endif //!_KVI_KVS_ALIASMANAGER_H_ diff --git a/src/modules/aliaseditor/aliaseditor.cpp b/src/modules/aliaseditor/aliaseditor.cpp index 26716ab0f..a1ec6d41c 100644 --- a/src/modules/aliaseditor/aliaseditor.cpp +++ b/src/modules/aliaseditor/aliaseditor.cpp @@ -443,26 +443,27 @@ void KviAliasEditor::oneTimeSetup() connect(KviKvsAliasManager::instance(),SIGNAL(aliasRefresh(const QString &)),this,SLOT(aliasRefresh(const QString &))); m_pTreeWidget->sortItems(0,Qt::AscendingOrder); } + void KviAliasEditor::aliasRefresh(const QString &szName) { - if(m_bSaving) return; + if(m_bSaving) + return; KviAliasTreeWidgetItem * item; KviKvsScript * alias = KviKvsAliasManager::instance()->aliasDict()->find(szName); item = createFullAliasItem(szName); if(item!=m_pLastEditedItem) { item->setBuffer(alias->code()); - } else { - if(QMessageBox::warning(0,__tr2qs("OverWrite Current Alias"), - __tr2qs("An external script has changed the alias you are currently editing. Do you want to accept the external changes?"), - QMessageBox::Yes,QMessageBox::No|QMessageBox::Default|QMessageBox::Escape) != QMessageBox::Yes) - { - return; - } else { - item->setBuffer(alias->code()); - m_pEditor->setText(alias->code()); - } + return; } + if( + QMessageBox::warning(0,__tr2qs("OverWrite Current Alias"), + __tr2qs("An external script has changed the alias you are currently editing. Do you want to accept the external changes?"), + QMessageBox::Yes,QMessageBox::No|QMessageBox::Default|QMessageBox::Escape) != QMessageBox::Yes + ) + return; + item->setBuffer(alias->code()); + m_pEditor->setText(alias->code()); } void KviAliasEditor::itemRenamed(QTreeWidgetItem *it,int col) @@ -1031,10 +1032,12 @@ void KviAliasEditor::appendSelectedItems(KviPointerList<KviAliasEditorTreeWidget void KviAliasEditor::removeItemChildren(KviAliasEditorTreeWidgetItem *it) { - for (int i=0;i<it->childCount();i++) + while(it->childCount() > 0) { - if (it->child(i)->childCount()) removeItemChildren((KviAliasEditorTreeWidgetItem *)it->child(i)); - delete it->child(i); + KviAliasEditorTreeWidgetItem * pChild = (KviAliasEditorTreeWidgetItem *)(it->child(0)); + if(pChild->childCount()) + removeItemChildren(pChild); + delete pChild; } } @@ -1075,7 +1078,8 @@ bool KviAliasEditor::removeItem(KviAliasEditorTreeWidgetItem *it,bool * pbYesToA m_pLastEditedItem = 0; if(it == m_pLastClickedItem) m_pLastClickedItem = 0; - if (it->childCount()) removeItemChildren(it); + if (it->childCount()) + removeItemChildren(it); delete it; return true; /* @@ -1495,7 +1499,8 @@ void KviAliasEditor::currentItemChanged(QTreeWidgetItem *it,QTreeWidgetItem *) void KviAliasEditor::recursiveCommit(KviAliasEditorTreeWidgetItem * it) { - if(!it)return; + if(!it) + return; if(it->isAlias()) { QString szName = buildFullItemName(it); @@ -1506,13 +1511,10 @@ void KviAliasEditor::recursiveCommit(KviAliasEditorTreeWidgetItem * it) KviKvsScript * a = new KviKvsScript(szName,((KviAliasTreeWidgetItem *)it)->buffer()); KviKvsAliasManager::instance()->add(szName,a); return; - } else - { - for (int i=0;i<it->childCount();i++) - { - recursiveCommit((KviAliasEditorTreeWidgetItem *) it->child(i)); - } } + + for (int i=0;i<it->childCount();i++) + recursiveCommit((KviAliasEditorTreeWidgetItem *) it->child(i)); } void KviAliasEditor::commit() @@ -1520,7 +1522,8 @@ void KviAliasEditor::commit() m_bSaving = true; saveLastEditedItem(); -// KviKvsAliasManager::instance()->clear(); + KviKvsAliasManager::instance()->clear(); + for(int i=0;i<m_pTreeWidget->topLevelItemCount();i++) { KviAliasEditorTreeWidgetItem *item=(KviAliasEditorTreeWidgetItem *)m_pTreeWidget->topLevelItem(i); |
