在使用QMAP的过程中发现导致程序崩溃的神奇问题,很有代表意义,所以把分析过程写出来,与大家共同学习。
一、问题描述
while(1)
{
QMapIterator<QString, int> i(map);
while (i.hasNext()) {
i.next();
qDebug() << i.key() << "1: " << i.value();
}
QMap<QString, int>::const_iterator i2 = map.constBegin();
while (i2 != map.constEnd()) {
qDebug() << i2.key() << "2: " << i2.value();
++i2;
}
QMap<QString, int>::iterator i3 = map.find(QString::number((int)this));
if( i3 != map.end() && i3.key() == QString::number((int)this) )
{
qDebug() << i3.key() << "3: " << i3.value();
}
}
上述代码中map为全局变量,多线程运行时会出现coredump
1、反馈上述3段遍历map的代码,屏蔽任何一段都不会coredump。(后来发现不对,屏蔽第2段时也会coredump)。
2、对全部代码加读锁时依然coredump,加写锁时正常。
3、根据代码分析应该没有对map的写操作,但是通过现象分析可能有对map的写操作。
二、源码分析
所以先看QMap的源码有没有对map的写操作,先看QMapIterator的源码
qiterator.h:
#define Q_DECLARE_MUTABLE_ASSOCIATIVE_ITERATOR(C) \
\
template <class Key, class T> \
class QMutable##C##Iterator \
{
\
typedef typename Q##C<Key,T>::iterator iterator; \
typedef typename Q##C<Key,T>::const_iterator const_iterator; \
typedef iterator Item; \
Q##C<Key,T> *c; \
iterator i, n; \
inline bool item_exists() const {
return const_iterator(n) != c->constEnd(); } \
public: \
inline QMutable##C##Iterator(Q##C<Key,T> &container) \
: c(&container) \
{
i = c->begin(); n = c->end(); } \
inline QMutable##C##Iterator &operator=(Q##C<Key,T> &container) \
{
c = &container; i = c->begin(); n = c->end(); return *this; } \
inline void toFront() {
i = c->begin(); n = c->end(); } \
inline void toBack() {
i = c