OpenCV 4.3.0 引入的错误 TlsStorage releaseSlot 导致 crash

1. 现象

动态库K使用了早于 OpenCV 4.3.0版本的静态库中的函数,
程序P使用了动态库K和OpenCV 4.3.0 ,
程序中涉及到与动态库K传递Mat数据

结果程序结束时会报错,信息如下:

1
2
3
OpenCV Error: Assertion failed (tlsSlots.size() > slotIdx) in releaseSlot, file /home/smarteye07/download/opencv/opencv320_static/modules/core/src/system.cpp, line 1092
terminate called after throwing an instance of 'cv::Exception'
  what():  /home/opencv/opencv320_static/modules/core/src/system.cpp:1092: error: (-215) tlsSlots.size() > slotIdx in function releaseSlot

后来测试发现:
单独使用 OpenCV 4.3.0 时,程序结束不会出现上述的错误,但是与其他库传递Mat数据时,就会出现数据释放失败导致的crash。

最后定位到这是OpenCV 4.3.0 新引入的错误。
OpenCV 4.1.1 及之前的版本没有这个错误。
OpenCV 4.2 看了源码,也是会有这个错误的。

2. 定位分析

发现问题出在 system.cpp 的 TlsStorage 类,然后就去逐行查看这部分的修改记录:
https://github.com/opencv/opencv/blame/master/modules/core/src/system.cpp

发现 opencv 官方在五个月前修改了 TlsStorage 的释放内存部分代码。
可能是这部分修改导致与老版本的释放不兼容,导致老版本在释放的时候会crash。

最后根据出版本时间,看到4.1.1版本这部分没有修改。

就用opencv411去进行测试,发现opencv411是没有这个问题的。

然后用opencv320去测试,也是没有这个问题的。

所以得出结论:此问题是opencv430新引入的错误,正好与上面的修改时间对得上。

关于导致crash的具体原因,没有仔细看,猜测是:

  1. 多个OpenCV版本释放Mat数据时,
  2. OpenCV 430 把Mat数据给释放了(其实这个时候还不应该释放),
  3. 导致OpenCV 320(或其他版本) 去释放的时候出现了断言错误。