[英]C++ Compile-time check that an overloaded function can be called with a certain type of argument
[英]C++: ensure in compile-time that function is only called on a specified thread
我有一种方法可以修补不是线程安全的复杂结构。 通常,这不是问题,因为对该方法的基本上所有调用都应在初始化阶段进行,该阶段应该在单个线程中运行(与我们以main()
开始的线程相同)。
但是,似乎我的代码库中的某些恶意组件确实在从非主线程调用此方法。 我显然可以在此方法中添加互斥锁/锁定防护,以防止潜在的调用,但是,从我的角度来看,这是一种解决方法,而不是我正在寻找的解决方案。
当然,我也可以添加一个运行时断言,例如:
static std::thread::id s_main_thread_id
int main(...) {
s_main_thread_id = std::this_thread::get_id();
// ...
}
void vulnerable_function() {
ASSERT(std::this_thread::get_id() == s_main_thread_id);
}
...但这不是保证。
问题:是否可以在编译时断言某个方法仅应从某个(即主)线程运行? 我想在我的代码库中找到流氓调用,并防止这种情况再次发生。
我已经研究过C ++ 20中类似断言的合同 ,但是如果我走对了路和/或可以采用它。
您可以做的是建立一些断言宏。 使用您的线程库获取线程标识符。 在您的代码首次构建该数据结构时,请保存线程ID。 然后,在每次输入这些功能时断言它与当前线程ID匹配。
CEF(铬嵌入式框架)库使用此库。
通过像断言一样包装这些宏,预处理器将在设置-DNDEBUG的发行版本中删除它们。
如果您不得不变得更高级,CEF还具有发布和处理消息的功能,以便其他线程可以通过向其发布消息来在UI线程上完成工作。
...所有对该方法的调用应在初始化阶段进行...
忘记线程。 如果仅在“初始化”期间调用该函数,请确保只能在初始化期间调用该函数:
boolean initialization_is_complete = false;
problematic_function(...) {
ASSERT(! initialization_is_complete);
...
}
initialize_the_system(...) {
...
call_things_that_call_problematic_function(...);
...
initialization_is_complete = true;
}
ASSERT()会在运行时发生,对吧?...我希望有一些静态分析工具能够在编译时[防止]这样做。
我不是C ++专家。 我所知道的防止“未经授权”使用任何东西的唯一编译时方法是将其声明对某个类或编译单元中的static
private
。*如果我可以使problematic_function()
在编译单元中为static
其公共符号仅在“初始”时间才有用,这就是我要做的。
另一方面,如果我的开发人员有充分的理由为什么要在其他时间从其他地方调用problematic_function()
,那么我将认真考虑重新设计它,这样就不会出现问题。
*如果您拉出一些我没想到的constexpr
技巧或template
技巧(我不是 C ++专家),那么我敢打赌,它仍将依赖于init代码范围内的某种声明,并超出所有其他代码的范围。
回到您最初的想法,即防止任何“错误的”线程调用该函数:实际上,没有C ++语言中的线程之类的东西。 std::thread
数据类型由库提供,并且编译器本身无法知道将执行其转换后的代码的线程的标识。
也就是说, std::this_thread::get_id()
不是constexpr
,并且没有编译时方法可以将它与程序中任何std::thread
的标识进行比较。
也许有一天他们会定义std::main_thread
...
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.