簡體   English   中英

C ++:確保在編譯時僅在指定線程上調用該函數

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM