簡體   English   中英

std::move 使 std::bind 中的該指針無效

[英]std::move disvalidates this pointer in std::bind

我有以下課程負責處理串行設備。 (請記住,我發布了重現我正在觀察的問題的最小示例。實際上有很多錯誤處理等,為了簡單起見,我將其刪除了 - 因此不要以此來評判我)

class Device
{
public:
    void open(const std::string& path) { 
        fd = ::open(path.c_str(), O_RDWR | O_NOCTTY));
        readThread = std::thread(std::bind(&Device::readProc, this)); 
    }
    void close() { ::close(fd); }

private:
    void readProc() { auto i = read(fd, buffer, sizeof(buffer)); }
    std::thread readThread;
    int fd;
};

在 main 中,我將枚舉每個設備,如果打開成功,我會將其推入向量中:

for (auto& p : std::filesystem::directory_iterator("/dev/"))
        if (p.path().string().substr(0, 11) == "/dev/ttyACM")
        {
            Device dev;
            if (dev.open(p.path().string()))
            {
                readers.push_back(std::move(dev));
            }
            else
            {
                std::cout << "Failed to open device " << p.path() << std::endl;
            }
        }

問題是,在調用std::move(dev)傳遞給std::bind函數的指針似乎無效。 read 返回 -1,errno 設置為 9(無效描述符)。 我已經調試了它,打開后fd的值為 5(隨着每次程序運行而變化),而在readProc() 中它在std::move之后變為 -129589(隨機值)。

這是正確的行為嗎? 如果是,如何避免?

編輯:我已將設備枚舉更改為:

readers.emplace_back();
auto& dev = readers.back();
if (!dev.open(p.path().string()))
{
    readers.pop_back();
}

這就像一個魅力,從而證實了我對 std::move() 的觀察,但這遠不是正確的方法。

這里:

readThread = std::thread(std::bind(&Device::readProc, this)); 

this綁定到傳遞給線程的函數。 然后當你打電話時

readers.push_back(std::move(dev));

然后dev被移動並且線程成員被移動,但線程仍然有一個指向被移動的對象的指針。

在您的固定版本中,情況並非如此,您在容器中已經存在的Device上調用open

這是正確的行為嗎?

是的。 移動對象dev仍然保持this不變。 而容器中的對象是不同的this

如果是,如何避免?

小心傳遞給線程的引用/指針。 通常,您需要注意引用/指向的對象仍然存在。

暫無
暫無

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

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