簡體   English   中英

Memory std::condition_variable 的位置可能導致 futex 錯誤

[英]Memory location of a std::condition_variable can cause futex error

我們的軟件中有一個錯誤以可怕的方式結束:

futex 工具返回了意外的錯誤代碼。

我們將其追溯到一個問題,即 std::condition_variable 在 memory 的 malloc 區域內的位置導致 futex 錯誤。 如果 std::condition_variable 未在 16 字節字上對齊 - 那么當您嘗試wait時它會導致 futex 錯誤。 在示例中,前兩個wait_for調用有效,但最后一個調用中止程序並出現 futex 錯誤。

void futex_error()
{
    /* init */
    std::mutex mtx;

    /* Normal one works  */
    std::cout << "Doing normal" << "\n";
    std::condition_variable* con_var = (std::condition_variable*)malloc(sizeof(std::condition_variable));
    new (con_var) std::condition_variable{};

    {
        std::unique_lock<std::mutex> lck(mtx);
        con_var->wait_for(lck, std::chrono::seconds(1));
    }

    /* Clean */
    con_var->std::condition_variable::~condition_variable();
    free(con_var);

    std::cout << "Doing 16 bytes" << "\n";
    /* Works on 16 byte alignment  */
    uint8_t* ptr_16 = (uint8_t*)malloc(sizeof(std::condition_variable) + 16);
    std::condition_variable* con_var_16 = new (ptr_16 + 16) std::condition_variable{};

    {
        std::unique_lock<std::mutex> lck(mtx);
        con_var_16->wait_for(lck, std::chrono::seconds(1));
    }

    /* Clean */
    con_var_16->std::condition_variable::~condition_variable();
    free(ptr_16);

    std::cout << "Doing 1 byte" << "\n";
    /* Futex error */
    uint8_t* bad_ptr = (uint8_t*)malloc(sizeof(std::condition_variable) + 1);
    std::condition_variable* bad = new (bad_ptr + 1) std::condition_variable{};

    {
        std::unique_lock<std::mutex> lck(mtx);
        bad->wait_for(lck, std::chrono::seconds(1)); //<--- error here?
    }

    /* Clean */
    bad->std::condition_variable::~condition_variable();
    free(con_var);
}

我似乎找不到有關 futex 錯誤的文檔以及為什么 alignment 會導致此錯誤。 有誰知道為什么會發生這種情況? 這是在 linux(Arch 和 Ubuntu)上,同時使用 gcc 9.3。

為什么 alignment 會導致這個

來自C++ 草稿 Alignment p1

Object 類型有 alignment 要求([basic.fundamental],[basic.compound]),這些要求限制了可以分配該類型的 object 的地址。

表達方式:

new (bad_ptr + 1) std::condition_variable{};

bad_ptr + 1未與alignof(std::condition_variable)對齊的系統上調用未定義行為。 使用 gcc10 在godbolt上測試alignof(std::confition_variable)等於8

兩個bad->訪問都是未對齊的訪問,並且都是未定義的行為。

有誰知道為什么會發生這種情況?

在執行可執行文件時檢查strace output,我們可以看到:

futex(0x557da3e262e9, FUTEX_WAIT_BITSET_PRIVATE, 0, {tv_sec=2439, tv_nsec=619296657}, FUTEX_BITSET_MATCH_ANY) = -1 EINVAL (Invalid argument)

因為uaddr第一個參數應該是futex調用的指向int的指針,沒有與_Alignof(int)對齊,所以 kernel 在這里檢測到它並且 futex 返回EINVAL 標准庫然后退出應用程序,這是未定義行為的完美行為。

找出我這個版本的來源“futex 工具返回了一個意外的錯誤代碼。” 錯誤信息。

它只是由#pragma pack(1)引起的,沒有在其他一些不相關的源代碼中返回正常打包。 然后 std::condition_variable 被初始化並且在使用時出錯。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

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