文章目录
- 摘要
- 尝试通过加锁解决
- lock&unlock
- QMutexLocker
- try_lock
- 改变量属性
- Q_ASSERT
- 参考
关键字:
ASSERT
、
isDetached
、
崩溃
、
QVector
、
Detach
摘要
今天在公司填坑的时候,有随机获得了一个新的BUG,就是一直报ASSERT:”isDetached()in file xxxxxx/qvector.h line 392如下图所示。
具体代码如下图所示:
虽然知道这是典型的多线程共享数据的BUG,但是我还是不知道该怎么处理。
尝试通过加锁解决
这里我都要奔溃了,各种加锁,包括在读QVector
的时候,基本算是凡是用到了QVector
就加锁的底部,还是会崩溃,整的我整个人都开始怀疑人生了。
lock&unlock
lock
Locks the mutex. If another thread has locked the mutex then this call will block until that thread has unlocked it.
Calling this function multiple times on the same mutex from the same thread is allowed if this mutex is a recursive mutex. If this mutex is a non-recursive mutex, this function will dead-lock when the mutex is locked recursively.
unlock
Unlocks the mutex. Attempting to unlock a mutex in a different thread to the one that locked it results in an error. Unlocking a mutex that is not locked results in undefined behavior.
最开始是直接使用lock 和unlock,来实现加锁和解算,但是发现不解决问题,其实这个在上一个项目中实践是好使用的,但是在这个项目里面都开始怀疑人生了。
QMutexLocker
和面百度到一个这个锁,官方对其描述如下:
Locking and unlocking a QMutex in complex functions and statements or in exception handling code is error-prone and difficult to debug. QMutexLocker can be used in such situations to ensure that the state of the mutex is always well-defined.
QMutexLocker should be created within a function where a QMutex needs to be locked. The mutex is locked when QMutexLocker is created. You can unlock and relock the mutex with unlock() and relock(). If locked, the mutex will be unlocked when the QMutexLocker is destroyed.
我理解就是更加智能一点锁,防止我们在加锁的时候,忘记解锁。但是还是没有解决。
try_lock
Attempts to lock the mutex. This function returns true if the lock was obtained; otherwise it returns false.
This function is provided for compatibility with the Standard Library concept Lockable. It is equivalent to tryLock().
The function returns true if the lock was obtained; otherwise it returns false
This function was introduced in Qt 5.8.
到这里,我就开始怀疑是不是我加锁失败了,导致资源竞争了,但是呢,还是失败了。通过判断,发现每次都可以成功加锁。但是还是不可以解决问题。
到这里,这个问题已经折腾我一天了。还是没有头绪。
改变量属性
开始我是在函数内部又 auto
了一个QVector
来接收线程的QVector
,就瞎几把想是不是在下一次调用函数的时候,又auto
了一个,到时其他函数在访问的时候,地址变了,出现了问题,所以给了一个全局的QVector
,结果还是没有效果。
Q_ASSERT
void Q_ASSERT(bool test)
Prints a warning message containing the source code file name and line number if test is false.
Q_ASSERT() is useful for testing pre- and post-conditions during development. It does nothing if QT_NO_DEBUG was defined during compilation.
Example:
// File: div.cpp
#include <QtGlobal>
int divide(int a, int b)
{
Q_ASSERT(b != 0);
return a / b;
}
If b is zero, the Q_ASSERT statement will output the following message using the qFatal() function:
ASSERT: "b != 0" in file div.cpp, line 7
See also Q_ASSERT_X(), qFatal(), and Debugging Techniques.
这个,用Qt 开发,避免不了,在做大型软件开发的时候,需要对程序进行调试,以确保程序内存的运算结果符合我们的预期,在不符合预期结果的时候,直接将程序断下,以便修改,
而 Q_ASSERT是一个在调试程序过程中用到的一个宏,在程序运行时,它计算传入参数表达式的值,若表达式结果为FALSE,程序将报告错误,并终止执行,如果表达式不为0,则继续执行后面的语句,他的作用是终止程序以免导致更严重的后果,同时也便于查找错误。
到这里,就要出现我的解决方案了,不过这里要申明一点,这个是重点
我的程序不会都在最终用户哪里使用,仅仅是为了某一种证书而开发的演示程序;我所避免崩溃的有方法基本就是哪痛割那的方法这个法子仅仅能在我当前的程序的里面试用,没有任何的参考价值,在正式的项目开中,最好还是要排查一下多线程共享数据的逻辑,已经互斥锁加的位置等等,绝对不推荐我这种方法,当然,我目前使用的Qt的版本是5.12.3,交叉编译的Qt版本也是厂家提供,这里不排除可能有Qt 的BUG,不过这个可能性基本可以说没有,我看了我当前使用的代码以及5.15.2版本的代码,如下图所示
5.15.2 是直接使用了std的realloc,而我所使用的5.12.3里面试用的是Qt 自己的一个,仅此而已。所以,我的方法就是把Q_ASSER给注释掉,因为当前是演示程序,所以数据有一定的风险,是我能接受的结果。但是,这里极度不推荐,不推荐,不推荐大家怎么搞。
参考
https://forum.qt.io/topic/90180/assert-isdetached-with-multithreaded-qvectors/2