金庆的专栏

  C++博客 :: 首页 :: 新随笔 :: 联系 :: 聚合  :: 管理 ::
  423 随笔 :: 0 文章 :: 454 评论 :: 0 Trackbacks
behaviac动态库运行出错

(金庆的专栏 2017.3.16)

游戏是静态链接的运行库,添加behaviac动态库后,运行出错:

>    ucrtbased.dll!free_dbg_nolock(void * const block, const int block_use) 行 996    C++
     ucrtbased.dll!_free_dbg(void * block, int block_use) 行 1030    C++
     libbehaviac_msvc_debug.dll!operator delete(void * block) 行 17    C++
     libbehaviac_msvc_debug.dll!std::_Deallocate(void * _Ptr, unsigned int _Count, unsigned int _Sz) 行 132    C++
     libbehaviac_msvc_debug.dll!std::allocator<std::_Container_proxy>::deallocate(std::_Container_proxy * _Ptr, unsigned int _Count) 行 720    C++
     libbehaviac_msvc_debug.dll!std::_Wrap_alloc<std::allocator<std::_Container_proxy> >::deallocate(std::_Container_proxy * _Ptr, unsigned int _Count) 行 988    C++
     libbehaviac_msvc_debug.dll!std::_String_alloc<std::_String_base_types<char,std::allocator<char> > >::_Free_proxy() 行 661    C++
     libbehaviac_msvc_debug.dll!std::_String_alloc<std::_String_base_types<char,std::allocator<char> > >::~_String_alloc<std::_String_base_types<char,std::allocator<char> > >() 行 629    C++
     libbehaviac_msvc_debug.dll!std::basic_string<char,std::char_traits<char>,std::allocator<char> >::~basic_string<char,std::char_traits<char>,std::allocator<char> >() 行 1018    C++
     libbehaviac_msvc_debug.dll!behaviac::CTagObject::Save(behaviac::IIONode * node, const char * szClassName) 行 100    C++
     libbehaviac_msvc_debug.dll!behaviac::Agent::InitVariableRegistry() 行 476    C++
     libbehaviac_msvc_debug.dll!behaviac::Agent::Init_(int contextId, behaviac::Agent * pAgent, short priority, const char * agentInstanceName) 行 227    C++
     giant_test_client.exe!behaviac::Agent::InitAgent(behaviac::Agent * pAgent, const char * agentInstanceName, const char * agentInstanceNameAny, bool bToBind, int contextId, short priority) 行 56    C++
     giant_test_client.exe!behaviac::Agent::Create<PlaneAgent>(const char * agentInstanceName, int contextId, short priority) 行 88    C++
     giant_test_client.exe!Client::InitPlayer() 行 36    C++
     giant_test_client.exe!Client::Client() 行 23    C++
     giant_test_client.exe!main() 行 50    C++
     giant_test_client.exe!invoke_main() 行 64    C++
     giant_test_client.exe!__scrt_common_main_seh() 行 253    C++
     giant_test_client.exe!__scrt_common_main() 行 296    C++
     giant_test_client.exe!mainCRTStartup() 行 17    C++
     kernel32.dll!@BaseThreadInitThunk@12()    未知
     ntdll.dll!___RtlUserThreadStart@8()    未知
     ntdll.dll!__RtlUserThreadStart@8()    未知

看来是string跨越动态库析构。
如果string在动态库中构造又析构,动态库的运行时库可以与主程序不同。
但如果用主程序的运行时申请内存,在动态库中用另一个运行时库释放,就会产生上面的错误。

可以建立一个最小化的程序来复现上面的错误。
新建一个行为树,为Agent创建一个属性。
然后主程序运行库设为:多线程调试 (/MTd),而不是:多线程调试 DLL (/MDd)。
调试运行创建Agent时就会出上面错误。

疑问是这是动态库内部调用,怎么会产生跨库析构呢?

断点进入string的构造过程可以发现,string不是动态库构造的,而是主程序构造的:

>    test_client.exe!behaviac::StringUtils::internal::ToString(const std::basic_string<char,std::char_traits<char>,std::allocator<char> > & val) 行 138    C++
     test_client.exe!behaviac::StringUtils::Detail::ToStringPtrHanler<std::basic_string<char,std::char_traits<char>,std::allocator<char> >,0>::ToString(const std::basic_string<char,std::char_traits<char>,std::allocator<char> > & v) 行 192    C++
     test_client.exe!behaviac::StringUtils::Detail::ToStringEnumHanler<std::basic_string<char,std::char_traits<char>,std::allocator<char> >,0>::ToString(const std::basic_string<char,std::char_traits<char>,std::allocator<char> > & v) 行 228    C++
     test_client.exe!behaviac::StringUtils::Detail::ToStringStructHanler<std::basic_string<char,std::char_traits<char>,std::allocator<char> >,0>::ToString(const std::basic_string<char,std::char_traits<char>,std::allocator<char> > & val) 行 242    C++
     test_client.exe!behaviac::StringUtils::ToString<std::basic_string<char,std::char_traits<char>,std::allocator<char> > >(const std::basic_string<char,std::char_traits<char>,std::allocator<char> > & val) 行 256    C++
     test_client.exe!behaviac::SetFromString_t<std::basic_string<char,std::char_traits<char>,std::allocator<char> >,0>::Get(std::basic_string<char,std::char_traits<char>,std::allocator<char> > & value) 行 790    C++
     test_client.exe!behaviac::CProperty<std::basic_string<char,std::char_traits<char>,std::allocator<char> > >::GetValueToString(const behaviac::Agent * self) 行 848    C++
     libbehaviac_msvc_debug.dll!behaviac::CTagObject::Save(behaviac::IIONode * node, const char * szClassName) 行 97    C++
     libbehaviac_msvc_debug.dll!behaviac::Agent::InitVariableRegistry() 行 476    C++
     libbehaviac_msvc_debug.dll!behaviac::Agent::Init_(int contextId, behaviac::Agent * pAgent, short priority, const char * agentInstanceName) 行 227    C++
     test_client.exe!behaviac::Agent::InitAgent(behaviac::Agent * pAgent, const char * agentInstanceName, const char * agentInstanceNameAny, bool bToBind, int contextId, short priority) 行 56    C++
     test_client.exe!behaviac::Agent::Create<PlaneAgent>(const char * agentInstanceName, int contextId, short priority) 行 88    C++
     test_client.exe!Client::InitPlayer() 行 36    C++
     test_client.exe!Client::Client() 行 23    C++
     test_client.exe!main() 行 50    C++
     test_client.exe!invoke_main() 行 64    C++
     test_client.exe!__scrt_common_main_seh() 行 253    C++
     test_client.exe!__scrt_common_main() 行 296    C++
     test_client.exe!mainCRTStartup() 行 17    C++
     kernel32.dll!75c3336a()    未知
     [下面的框架可能不正确和/或缺失,没有为 kernel32.dll 加载符号]    
     ntdll.dll!76fa9902()    未知
     ntdll.dll!76fa98d5()    未知

原因为 IProperty::GetValueToString()是虚函数,实际实现是由主程序实现模板类。
    behaviac::CProperty<>::GetValueToString()

解决方案为使用behaviac静态库并且静态链接运行时库。
posted on 2017-03-16 11:40 金庆 阅读(726) 评论(0)  编辑 收藏 引用 所属分类: 1. C/C++2. 网游开发

只有注册用户登录后才能发表评论。
网站导航: 博客园   IT新闻   BlogJava   知识库   博问   管理