У меня есть следующий класс, который заботится о последовательном устройстве. (Пожалуйста, имейте в виду, что я опубликовал минимальный пример, который воспроизводит проблему, которую я наблюдаю. На самом деле существует множество обработчиков ошибок и т. Д. c, которые я удалил для простоты - поэтому не судите меня по этому вопросу)
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;
};
в основном, я перечислю каждое устройство, и если открытие было успешным, заболею его sh в вектор:
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 (меняется при каждом запуске программы), тогда как в readPro c () оно становилось -129589 (случайное значение) после std::move
.
Это правильное поведение? Если так, как этого можно избежать?
Редактировать: Я изменил перечисление устройства на:
readers.emplace_back();
auto& dev = readers.back();
if (!dev.open(p.path().string()))
{
readers.pop_back();
}
, который работал как шарм, таким образом подтверждая мой замечания относительно std :: move (), но это далеко не правильный способ сделать это.