Является ли законным называть memchr слишком длинной длиной, если вы знаете, что персонаж будет найден до достижения допустимого региона?

Является следующее определенное поведение в C11 и C ++ 11 1 ?

bool has4() { char buf[10] = {0, 1, 2, 4}; return memchr(buf, 4, 20); } 

Здесь мы пропускаем слишком длинную длину в memchr . Массив имеет 10 элементов, но мы проходим 20. Элемент, который мы ищем, однако, всегда находится до конца. Для меня это ясно, если это законно.

Если это разрешено, это ограничит гибкость реализации, поскольку реализация не может полагаться на размер, являющийся допустимым показателем размера доступной области памяти и, следовательно, должен быть осторожным при чтении за пределами найденного элемента. Примером может служить реализация, которая хочет выполнить 16-байтовую нагрузку SIMD, начиная с указателя, и затем проверять все 16 байтов параллельно. Если пользователь передает длину 16, это будет безопасно только в том случае, если требуется полная длина всей длины.

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


1 Вот один из тех редких вопросов, по которым я предполагаю, что tags C и C ++ действительны: насколько я могу сказать, что стандарт C ++ просто отсылает непосредственно к стандарту C здесь, через ссылку, с точки зрения поведения, но если это не так Я хочу знать.

В C11 и C ++ 17 ( акцент мой )

void *memchr(const void *s, int c, size_t n);

Функция memchr обнаруживает первое вхождение c (преобразованное в unsigned char ) в начальные n символов (каждый интерпретируется как unsigned char ) объекта, на который указывает s . Реализация должна вести себя так, как если бы она читала символы последовательно и останавливалась, как только найден соответствующий символ.

Пока memchr находит то, что он ищет, прежде чем вы выходите за пределы, вы в порядке.


C ++ 11 и C ++ 14 используют C99, который не имеет такой формулировки. (Они относятся к ISO / IEC 9899: 1999)

C99:

void *memchr(const void *s, int c, size_t n);

Функция memchr обнаруживает первое вхождение c (преобразованное в unsigned char ) в начальные n символов (каждый интерпретируется как unsigned char ) объекта, на который указывает s .

Не определяя, что произойдет, если вы пройдете слишком большой размер, поведение не определено в C99