墓碑内容是:
signal 11 (SIGSEGV), code 1 (SEGV_MAPERR), fault addr 0x10
Cause: null pointer dereference
backtrace:
#00 pc 0000000000069568 /system/lib64/vndk-sp-28/libc++.so (std::__1::future<void>::~future()+40)
#01 pc 000000000000a6ec /vendor/lib64/xxx.so(我自己的 so) (android::BatchingConsumer<std::__1::shared_future<void>>::runInternal(std::__1::function<void (std::__1::vector<std::__1::shared_future<void>, std::__1::allocator<std::__1::shared_future<void>>> const&)> const&)+276)
#02 pc 000000000000ab4c /vendor/lib64/xxx.so (_ZNSt3__114__thread_proxyINS_5tupleIJNS_10unique_ptrINS_15__thread_structENS_14default_deleteIS3_EEEEMN7android16BatchingConsumerINS_13shared_futureIvEEEEFvRKNS_8functionIFvRKNS_6vectorISA_NS_9allocatorISA_EEEEEEEEPSB_SK_EEEEEPvSR_+68)
#03 pc 0000000000082fec /system/lib64/libc.so (__pthread_start(void*)+36)
#04 pc 000000000002337c /system/lib64/libc.so (__start_thread+68)
但是看了半天,总觉得是不可能挂在析构函数的啊。而且这个问题也不是必现的,大部分时候机能都能正常工作。但一旦发生了这个墓碑,机器就会重启,就很严重。
关于 future 的使用过程也很简单:
std::shared_future<void> _future = std::async(std::launch::deferred,
[=]() -> void {
//balabala
});
就是使用一个 future 来包装一个 lambda 表达式(这里没有使用到 future 的异步功能,因为是 deferred ),然后将这个 future 放到一个消息队列里面去,然后与这个消息队列相关的有一个唯一消费者线程会被唤醒,然后这个线程将这个 future 对象出队,执行_future.wait()
,因为消费者的 run 方法就是一个死循环不断出队 task 对象(也就是我们的 future 对象),所以在死循环的最后的大括号那里,会自动执行这个 future 对象的析构函数。
上面的过程大多数时候都好使,但有的时候就会出现墓碑,这种问题到底可能是什么造成的啊?如果对象为 null,那么在执行_future.wait()
的时候就应该报错啊,但现在却是在析构函数的时候报错。
看了网上相关内容,可能也就这个有关系:
https://zhuanlan.zhihu.com/p/39757902 提到的 std::async 会抓走所有异常。 https://blog.csdn.net/weixin_34256074/article/details/89412245 的匿名 std::thread 对象(感觉这个也和我这个没有关系)。
刚又想到一点,难道跟 lambda 的参数捕获有关系吗?我用的复制[=]()
这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。
V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。
V2EX is a community of developers, designers and creative people.