Почему опрос требует, чтобы его основной параметр жил за пределами вызова?

Я изучаю функцию poll() для моего небольшого проекта и заметил, что этот фрагмент разбился:

ErrorCode XNotifier_Linux::updatePoll()
{
    ErrorCode ret = Success;

    struct pollfd descriptors = { m_fd, IN_MODIFY, 0 };
    const int nbDescriptors = poll(&descriptors, m_fd+1, 10*1000);

    if (descriptors.events & (POLLIN | POLLPRI))
        ret = DataIsPresent;

    return ret;
}

Valgrind весьма полезен, потому что указывает на то, что поле poll ufds в унифицированном виде:

==833== Syscall param poll(ufds.fd) points to uninitialised byte(s)
==833==    at 0x569CB28: poll (in /lib64/libc-2.14.1.so)
==833==    by 0x400F7A: xnot::XNotifier_Linux::updatePoll() (linux.cpp:72)
==833==    by 0x400D4B: xnot::XNotifier_Linux::update() (linux.cpp:28)
==833==    by 0x400FF4: main (linux.cpp:90)
==833==  Address 0x7fefffbb8 is on thread 1's stack

Как descriptors был создан в стеке, я понимаю, что когда функция возвращает, указатель на descriptors больше не действителен Я думал, что этот указатель может быть использован после возврата функции. Чтобы подтвердить это, я изменил строку объявления дескрипторов на: static struct pollfd descriptors = { m_fd, IN_MODIFY, 0 }; и авария исчезла.

Почему дескрипторы должны переживать вызов poll()? (Или я что-то не так понял?)

P.-S.: дескриптор был заполнен inotify m_fd = inotify_init();

1 ответ

Решение

Вы неправильно определили проблему.

const int nbDescriptors = poll(&descriptors, m_fd+1, 10*1000);

Это неправильно, потому что первый аргумент poll массив (указатель на), а второй аргумент - количество элементов в этом массиве.

В результате системный вызов выполняет чтение за концом массива. Объявив это static ты просто переместил вещи в память и повезло.

Тебе нужно:

const int nbDescriptors = poll(&descriptors, 1, 10*1000);
Другие вопросы по тегам