Сравнение 2 указателей со структурой с гибким членом массива - PullRequest
0 голосов
/ 02 марта 2020

ВОПРОС: Законно ли сравнивать 2 указателя с гибкими элементами массива для более чем (меньше) и равенства?


Вот как объявляется struct inotify_event в Linux:

struct inotify_event {
           int      wd;       /* Watch descriptor */
           uint32_t mask;     /* Mask describing event */
           uint32_t cookie;   /* Unique cookie associating related
                                 events (for rename(2)) */
           uint32_t len;      /* Size of name field */
           char     name[];   /* Optional null-terminated name */
       };

Опуская проверки размера для простоты, давайте рассмотрим следующий код:

int inotify_fd = inotify_init();
//...
struct inotify_event *ino_buf = malloc(sizeof(inotify_event) * 4096);
read(inotify_fd, ino_buf, sizeof(inotify_event) * 4096));
struct inotify_event *first_event = ino_buf;
struct inotify_event *second_event = 
           ((char *) ino_buf) + sizeof(struct inotify_event) + first_event->len;
if(first_event < second_event){ //UB?
    //...
}

Я думаю, что сравнение указателей на структуру, содержащую гибкий член массива всегда UB (даже если они одинаковые)

N2346/6.7.2.1p3 (emp. mine):

последний элемент структуры с более чем одним именованным элементом может иметь неполный тип массива; такая структура (и любое объединение, содержащее, возможно, рекурсивно, член, который является такой структурой) не должно быть членом структуры или элементом массива .

OTOH, N2346/6.5.8p5 требуется, чтобы сравниваемые указатели принадлежали одному и тому же массиву:

Когда сравниваются два указателя, результат зависит от относительного расположения в адресном пространстве объекты, на которые указывают. Если два указателя на типы объектов оба указывают на один и тот же объект или оба указывают один за последним элементом одного и того же объекта массива, они сравниваются одинаково. Если указанные объекты являются членами одного и того же агрегатного объекта, указатели на элементы структуры, объявленные позже, сравниваются больше, чем указатели, на элементы, объявленные ранее в структуре, а указатели на элементы массива с большими значениями нижнего индекса сравниваются больше, чем указатели на элементы того же массива. с более низкими значениями индекса. Все указатели на члены одного и того же объекта объединения сравниваются одинаково. Если выражение P указывает на элемент объекта массива, а выражение Q указывает на последний элемент того же объекта массива, выражение указателя Q + 1 сравнивается больше, чем P. Во всех других случаях поведение не определено.

OTOOH, я обнаружил N2346/6.5.8p4, противоречащим определению структур с гибкими элементами массива:

Для целей из этих операторов указатель на объект, который не является элементом массива, ведет себя так же, как указатель на первый элемент массива длиной один с типом объекта в качестве его типа элемента.

Это означает, что, поскольку struct inotify_event *first_event никогда не является элементом массива, N2346/6.7.2.1p3, поэтому его можно рассматривать как элемент массива длины один, что противоречит N2346/6.7.2.1p3

1 Ответ

1 голос
/ 04 марта 2020

Если T является структурой, содержащей элемент гибкого массива, нельзя объявлять объекты или типы в форме T[intVal]; это ограничение времени компиляции, требующее, чтобы компиляторы выдавали диагностику c, если программа пытается объявить такой массив.

В отдельном разделе Стандарта указывается, что указатель на объект типа T будет вести себя как указатель на объект типа T[1]. Я не думаю, что есть намерение исключить структуры с гибкими элементами массива из этого положения в тех случаях, когда это целесообразно применить. Попытка объявить объект или typedef типа T[1] была бы нарушением ограничения, требующего диагностики c, и было бы невозможно иметь два несовпадающих указателя типа T, которые были бы частью одного и того же массив, но для качественной реализации не было бы никакой причины не рассматривать реляционное сравнение двух указателей с одним и тем же объектом типа T, как если бы они сравнивали два указателя с одним и тем же элементом одного и того же массива.

...