通过比较boost::function的functor.members.func_ptr注销监听器安全吗?
你通过访问boost::function内部members.func_ptr做比较的做法不具备生产环境的安全性,存在多个不可忽视的隐患:
members属于boost::function的私有内部实现,不属于公开API的承诺范围。Boost官方没有对该成员的存在、结构、存储逻辑做任何兼容性保证,一旦Boost版本升级、或者编译参数调整(比如开启/关闭小对象优化、调整对齐规则),相关逻辑直接失效,轻则编译报错,重则出现难以排查的运行时逻辑错误。func_ptr的比较逻辑无法覆盖所有场景,极易出现误判:- 两个完全独立、功能不同的可调用对象,可能因为
boost::function内部的转发逻辑共用同一个thunk函数指针,导致func_ptr对比结果相等,出现「删错回调」的问题。 - 同一个可调用对象经过多次拷贝、包装生成不同的
boost::function实例时,内部func_ptr也可能出现不一致,导致「明明是同一个回调却删不掉」的问题。
- 两个完全独立、功能不同的可调用对象,可能因为
- 你预设的「同一个可调用对象地址唯一」逻辑并不成立。你在事件管理器中存储的是用户传入回调的拷贝,和用户侧持有的原始可调用对象本身就不是同一个内存地址,即使内部函数指针一致,也无法保证二者绑定的上下文(比如lambda捕获的变量、
boost::bind绑定的参数)完全相同,对比逻辑从根源上就有漏洞。
更稳妥的实现方式是放弃直接比较回调对象的思路,在注册回调时给每个回调生成一个全局唯一的整数token返回给调用方,注销时直接传入对应token即可匹配到对应回调,完全规避函数对象比较的问题,兼容性和可维护性都更强。
内容的提问来源于stack exchange,提问作者Frederic Schönberger
相关产品推荐
相关产品推荐

