QT删除可与Valgrind一起使用,但不能正常执行

Qt delete works with Valgrind but not normal execution

本文关键字:常执行 但不能 执行 删除 Valgrind 一起 QT      更新时间:2023-10-16

我正在使用qtCreator和valgrind在QT程序中检查内存泄漏。我正在删除在灾难中的Qhash中的一些条目:

QHash<QString, QVariant*> m_Hash;
/**
 * @brief
 * Destruct a Foo Class instance
 */
Foo ::~Foo ()
{
    // Do Cleanup here
    // Delete hash leftovers
    foreach( QString key, m_Hash.keys() )
    {
        qDebug() << "Deleting an entry..";
        // Delete the hash item
        delete m_Hash.take(key);
    }
}

如果我使用Valgrind进行调试,则此代码很好,并在称为destructor时删除内容:

>> Deleting an entry.. 
>> Deleting an entry.. 

如果我在qtCreator中使用GDB启动,则从qtCreator启动,或者只需从命令行运行我的qt应用程序,我会得到分割错误!

Signal name : 
SIGSEGV
Signal meaning : 
Segmentation fault

如果我赞扬"删除"行,那么我可以使用任何方法运行我的应用程序,但是我确实泄漏了内存。

什么给?Valgrind是否引入了某种延迟,使我的驱动器可以工作?我该如何解决?

hyde的答案正确;但是,清除特定哈希的最简单方法如下:

#include <QtAlgorithms>
Foo::~Foo()
{
   qDeleteAll(m_Hash);
   m_Hash.clear();
}

请注意,如果哈希表的键是指针(例如QHash<QString*, QVariant>)。

您无法通过foreach修改您的容器。改用迭代器。使用方法iterator QHash::erase ( iterator pos )正确代码:

 QMap<QString, QVariant* >::iterator it = m_Hash.begin();
 // auto it = m_Hash.begin(); // in C++11
 while (it != m_Hash.end()) {
     delete it.value();
     it = m_Hash.erase(it);
 }

另外,您要存储QVariant指针而不是价值的任何特定原因?Qvariant通常适合保持值为价值,因为您存储在QVariant中的大多数数据是隐式共享的,或者很小。

文档没有明确提及它,但是您正在突变您正在迭代的容器。

foreach的代码在这里。

查看代码,IT和您的代码基本上与您要编写的代码相同:

for (QHash::iterator it=m_Hash.begin(), end=m_Hash.end(); 
     it!=end;
     ++it)
{
    delete m_Hash.take(key);
}

但是,take成员函数可能会触发现有迭代器的无效(itend),因此您的迭代器可能已经悬挂,产生了未定义的行为。

可能的解决方案:*请勿在迭代时通过修改容器您的迭代器*确保it在下一次迭代开始之前有效,并且不要存储end-列表(此解决方案禁止使用foreach

也许foreach关键字存在问题。尝试更换:

foreach( QString key, m_Hash.keys() )
{
    qDebug() << "Deleting an entry..";
    delete m_Hash.take(key);  // take changes the m_Hash object
}

with:

for (QHash<QString, QVariant*>::iterator it =  m_Hash.begin();
                                         it != m_Hash.end(); ++it)
{
    qDebug() << "Deleting an entry..";
    delete it.value();      // we delete only what it.value() points to, but the 
                            // m_Hash object remains intact.
}
m_Hash.clear();

这样,在您迭代它时,哈希表保持不变。foreach宏可能会扩展到您"从脚下删除凸面"的结构。那是宏可能会产生一个迭代器,它成为无效或"悬空"作为调用的副作用

m_Hash.take(key);
相关文章: