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-12-25安卓NDK 是什么?-icode9专业技术文章分享
- 2024-12-25caddy 可以定义日志到 文件吗?-icode9专业技术文章分享
- 2024-12-25wordfence如何设置密码规则?-icode9专业技术文章分享
- 2024-12-25有哪些方法可以实现 DLL 文件路径的管理?-icode9专业技术文章分享
- 2024-12-25错误信息 "At least one element in the source array could not be cast down to the destination array-icode9专业技术文章分享
- 2024-12-25'flutter' 不是内部或外部命令,也不是可运行的程序 或批处理文件。错误信息提示什么意思?-icode9专业技术文章分享
- 2024-12-25flutter项目 as提示Cannot resolve symbol 'embedding'提示什么意思?-icode9专业技术文章分享
- 2024-12-24怎么切换 Git 项目的远程仓库地址?-icode9专业技术文章分享
- 2024-12-24怎么更改 Git 远程仓库的名称?-icode9专业技术文章分享
- 2024-12-24更改 Git 本地分支关联的远程分支是什么命令?-icode9专业技术文章分享