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