OceanBase 源码中 static 变量析构顺序导致的 coredump
2021/12/23 17:12:25
本文主要是介绍OceanBase 源码中 static 变量析构顺序导致的 coredump,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!
问题背景
在 OceanBase 开源代码中,有这样一段代码,它会导致在系统退出时发生 coredump:
oceanbase::sql::ObSQLSessionInfo &session() { static oceanbase::sql::ObSQLSessionInfo SESSION; return SESSION; } ObArenaAllocator &session_alloc() { static ObArenaAllocator SESSION_ALLOC; return SESSION_ALLOC; } int ObTableApiProcessorBase::init_session() { int ret = OB_SUCCESS; static const uint32_t sess_version = 0; static const uint32_t sess_id = 1; static const uint64_t proxy_sess_id = 1; if (OB_FAIL(session().test_init(sess_version, sess_id, proxy_sess_id, &session_alloc()))) { LOG_WARN("init session failed", K(ret)); } // more ... return ret; }
利用 ASAN 诊断发现,静态对象 SESSION 析构时会引用一个 SESSION_ALLOC,而 SESSION_ALLOC 也是一个静态对象,当 SESSION_ALLOC 先于 SESSION 析构时,SESSION 析构时就会访问到非法内存(因为 SESSION_ALLOC 已经析构)。
C 语言中,对于 static 变量,析构规则是:先构造者后析构 可以用下面的程序来验证:
[xiaochu.yh ~] $cat test_destroy.cpp // Copyright 1999-2021 Alibaba Inc. All Rights Reserved. // Author: // xiaochu.yh@alipay.com // // test static variable destory order #include <iostream> using namespace std; class A { public: A() { cout << "construct A" << endl; } ~A() { cout << "deconstruct A" << endl; } void init() {} }; class B { public: B() { cout << "construct B" << endl; } ~B() { cout << "deconstruct B" << endl; } void init(A &a) { a.init(); } }; A &getA() { static A a; return a; } B &getB() { static B b; return b; } void func() { getB().init(getA()); } int main(int argc, const char *argv[]) { func(); return 0; } [xiaochu.yh ~] $g++ test_destroy.cpp -o test_destroy [xiaochu.yh ~] $./test_destroy construct A construct B deconstruct B deconstruct A
修复方法
既然先构造者后析构 ,那么我们可以在 SESSION 构造之前,主动调用一次 session_alloc,使得 SESSION_ALLOC 先构造即可。
代码如下:
oceanbase::sql::ObSQLSessionInfo &session() { static oceanbase::sql::ObSQLSessionInfo SESSION; return SESSION; } ObArenaAllocator &session_alloc() { static ObArenaAllocator SESSION_ALLOC; return SESSION_ALLOC; } int ObTableApiProcessorBase::init_session() { int ret = OB_SUCCESS; static const uint32_t sess_version = 0; static const uint32_t sess_id = 1; static const uint64_t proxy_sess_id = 1; // ensure allocator is constructed before session to // avoid coredump at observer exit ObArenaAllocator &dummy_allocator = session_alloc(); UNUSED(dummy_allocator); if (OB_FAIL(session().test_init(sess_version, sess_id, proxy_sess_id, &session_alloc()))) { LOG_WARN("init session failed", K(ret)); } // more ... return ret; }
这篇关于OceanBase 源码中 static 变量析构顺序导致的 coredump的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!
- 2024-05-25Elevate Your Lead Generation Game with Maps Scraper AI
- 2024-05-15PingCAP 黄东旭参与 CCF 秀湖会议,共探开源教育未来
- 2024-05-13PingCAP 戴涛:构建面向未来的金融核心系统
- 2024-05-09flutter3.x_macos桌面os实战
- 2024-05-09Rust中的并发性:Sync 和 Send Traits
- 2024-05-08使用Ollama和OpenWebUI在CPU上玩转Meta Llama3-8B
- 2024-05-08完工标准(DoD)与验收条件(AC)究竟有什么不同?
- 2024-05-084万 star 的 NocoDB 在 sealos 上一键起,轻松把数据库编程智能表格
- 2024-05-08Mac 版Stable Diffusion WebUI的安装
- 2024-05-08解锁CodeGeeX智能问答中3项独有的隐藏技能