Nambers / MiraiCP

c++ SDK of Mirai
https://eritque-arcus.tech/MiraiCP/
GNU Affero General Public License v3.0
176 stars 31 forks source link

std::regex 在插件中无法正常使用,throw bad_cast #142

Closed Antares0982 closed 1 year ago

Antares0982 commented 1 year ago

Code of Conduct

问题描述

std::regex在插件中(Debug,release)构造时,抛出std::bad_cast异常,但在gtest中不会出现任何问题。

在插件OnEnable函数中加入下面语句:

std::use_facet<std::collate<char>>(std::locale());

进行测试,堆栈信息已在下方日志中。gtest运行时并非像实际运行时那样是通过运行时链接,而是编译期链接,根据此结论查找到了相关的资料 https://gcc.gnu.org/bugzilla/show_bug.cgi?id=52540 ,但目前没有非常好的解决方案。

细节及已经尝试过的解决方案:

日志

__cxa_throw 0x00007fffc5979040
__cxa_bad_cast 0x00007fffc589cccd
std::__cxx11::collate<char> const& std::use_facet<std::__cxx11::collate<char> >(std::locale const&) 0x00007fffc59a50f4
Main::onEnable test.cpp:84
FUNC_ENTRANCE utils.cpp:56
LibLoader::callEntranceFuncNormal PluginListImplements.cpp:123
operator() PluginListImplements.cpp:180
std::__invoke_impl<…>(std::__invoke_other, struct {...} &) invoke.h:61
std::__invoke_r<…>(struct {...} &) invoke.h:111
std::_Function_handler::_M_invoke(const std::_Any_data &) std_function.h:290
std::function::operator()() const std_function.h:591
LibLoader::ThreadController::threadWorker::_do_job(const std::function<…> &) ThreadController.cpp:49
LibLoader::ThreadController::threadWorker::run ThreadController.cpp:100
operator() ThreadController.cpp:160
std::__invoke_impl<…>(std::__invoke_other, struct {...} &&) invoke.h:61
std::__invoke<…>(struct {...} &&) invoke.h:96
std::thread::_Invoker::_M_invoke<…>(std::_Index_tuple<…>) std_thread.h:252
std::thread::_Invoker::operator()(void) std_thread.h:259
std::thread::_State_impl::_M_run(void) std_thread.h:210
execute_native_thread_routine 0x00007fffc5e5efa3
<unknown> 0x00007ffff7df18fd
<unknown> 0x00007ffff7e73a60

版本

v2.13.0-alpha

组件

Plugin(SDK)

编译器

gcc/g++, 其他

系统

Linux/Unix

架构

x86-64/amd64

Antares0982 commented 1 year ago

尝试禁用RTTI,无效

Antares0982 commented 1 year ago

https://stackoverflow.com/questions/45843937/what-could-make-dynamic-cast-start-throwing-stdbad-cast-even-if-invoked-on-poin

Antares0982 commented 1 year ago
Antares0982 commented 1 year ago

已经明确地在编译选项里禁用了rtti,但是链接上外部模板特化的代码还是调用了dynamic cast,以及使用了collate<char>类型的typeid。

Antares0982 commented 1 year ago

尝试删除redirect cout相关的所有代码,无效

Antares0982 commented 1 year ago

发现一个临时的解决方案:

memcpy(&std::collate<char>::id, &std::collate<int8_t>::id, sizeof(std::collate<int8_t>::id));

除此之外,注意到如果直接通过可执行程序调用dlopen()打开一个动态链接库并运行,use_facet是不会抛出错误的,估计问题仅会在java运行时出现

Antares0982 commented 1 year ago

同样的问题会在libLoader出现,推测是jvm那边修改了stdout相关的东西导致的问题

Antares0982 commented 1 year ago

问题排查到了,是oracle jdk会导致这个bug,jdk 17, 18均可复现,并且要在linux平台上。提醒用户不要用linux + oracle jdk就可以