Почему опрос требует, чтобы его основной параметр жил за пределами вызова? - PullRequest
3 голосов
/ 24 февраля 2012

Я изучаю функцию 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 весьма полезен здесь, потому что он указывает, что поле опроса 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 Ответ

8 голосов
/ 24 февраля 2012

Вы ошибочно определили проблему.

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

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

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

Вам нужно:

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