Skia下SK_DEBUG内联的坑

本文约 500 字,阅读需 1 分钟。

以下代码可能出现看起来诡异的错误

{
   auto data = image->encodeToData();
    std::stringstream ss;
    ss << count++ << "_output.png";
    if (data) {
        SkFILEWStream out(ss.str().c_str());
        out.write(data->writable_data(), data->size());
    }
}

错误如下:

* thread #3, name = 'RasterThread', stop reason = signal SIGILL: illegal operand
  * frame #0: 0x000000000c02edd4 Sxxxx`sk_abort_no_print() at SkMemory_malloc.cpp:51:5
    frame #1: 0x000000000bbbee39 Sxxxx`SkNVRefCnt<SkData>::~SkNVRefCnt(this=0x00007fffafdff530)::'lambda'()::operator()() const at SkRefCnt.h:165:9
    frame #2: 0x000000000bbbec35 Sxxxx`SkNVRefCnt<SkData>::~SkNVRefCnt(this=0x00007fffa8006090) at SkRefCnt.h:165:9
    frame #3: 0x000000000bbbd8ba Sxxxx`SkData::~SkData(this=0x00007fffa8006090) at SkData.cpp:37:1

具体是因为这个ASSERT:

    ~SkNVRefCnt() {
    #ifdef SK_DEBUG
        int rc = fRefCnt.load(std::memory_order_relaxed);
        SkASSERTF(rc == 1, "NVRefCnt was %d", rc);
    #endif
    }

我们的工程是使用include + .a库集成的,工程并没有设置SK_DEBUG,按理这个逻辑不应该触发…..

Debug时,发现有以下信息:

(lldb) s
Process 5195 stopped
* thread #3, name = 'RasterThread', stop reason = step in
    frame #0: 0x0000000009383401 Sxxxx`WebCore::xxxxxx [inlined] SkNVRefCnt<SkData>::unref(this=0x00007fffa8006090) const at SkRefCnt.h:180:13
(lldb) p fRefCnt
(std::atomic<int>) {
  std::__atomic_base<int> = (_M_i = 0)
}
(lldb) s
Process 5195 stopped
* thread #3, name = 'RasterThread', stop reason = step in
    frame #0: 0x000000000bbbd8b4 Sxxxx`SkData::~SkData(this=0x00007fffa8006090) at SkData.cpp:34:9
(lldb)

注意SkData的定义:

class SK_API SkData final : public SkNVRefCnt<SkData> {
  ....

.a库是Debug库,但看起来SkData::~SkData内联了SkNVRefCnt的析构….真是及不胜防。

相关头文件如下图: 20240919112546

按照这个原因,打开skia/include/config/SkUserConfig.h的SK_DEBUG,果然Crash没有了。

总阅读量次。