Прямой ответ на вопрос
Мне нравится ответ Роберта, но у меня также есть некоторые мнения по поднятым мной вопросам.
Используете ли вы библиотеку или компилятор с поддержкой функций TR24731-1?
Нет, не знаю.
Если да, то какой компилятор или библиотека и на какой платформе (ях)?
Я полагаю, что функции предоставляются MS Visual Studio (например, MS VC ++ 2008 Edition), и есть предупреждения, которые побуждают вас использовать их.
Вы обнаружили какие-либо ошибки в результате исправления вашего кода для использования этих функций?
Пока нет. И я не ожидаю раскрыть многие в моем коде. Некоторый другой код, с которым я работаю - возможно. Но я еще не убежден.
Какие функции обеспечивают наибольшее значение?
Мне нравится тот факт, что семейство функций printf_s () не принимает спецификатор формата '%n
'.
Есть ли такие, которые не дают значения или отрицательного значения?
Функции tmpfile_s()
и tmpnam_s()
- ужасное разочарование. Им действительно нужно было работать больше как mkstemp()
, который одновременно создает файл и открывает его, чтобы гарантировать отсутствие уязвимости TOCTOU (время проверки, время использования). В их нынешнем виде эти два дают очень мало значения.
Я также думаю, что strerrorlen_s()
дает очень небольшое значение.
Планируете ли вы использовать библиотеку в будущем?
У меня две мысли об этом. Я начал работать над библиотекой, которая будет реализовывать возможности TR 24731 по сравнению со стандартной библиотекой C, но был пойман количеством модульного тестирования, необходимого, чтобы продемонстрировать, что он работает правильно. Я не уверен, стоит ли продолжать это. У меня есть некоторый код, который я хочу портировать на Windows (в основном из-за извращенного желания обеспечить поддержку на всех платформах - он работает над производными Unix уже пару десятилетий). К сожалению, чтобы заставить его компилироваться без предупреждений от компиляторов MSVC, я должен оштукатурить код, чтобы не допустить засорения MSVC, используя совершенно надежные (при тщательном использовании) стандартные функции библиотеки C. И это не аппетитно. Достаточно плохо, что мне приходится иметь дело с системой, которая развивалась в течение этого периода в течение большей части двух десятилетий; необходимость иметь дело с чьей-то идеей веселья (заставляющей людей принимать TR 24731, когда им это не нужно) раздражает. Это было частично, почему я начал разработку библиотеки - чтобы позволить мне использовать те же интерфейсы в Unix и Windows. Но я не уверен, что я буду делать отсюда.
Вы вообще отслеживаете работу TR24731-2?
Я не отслеживал его, пока не зашел на сайт стандартов во время сбора данных для вопроса. Функции asprintf()
и vasprintf()
, вероятно, полезны; Я бы использовал их. Я не уверен насчет функций ввода-вывода потока памяти. Стандартизация strdup()
на уровне C была бы огромным шагом вперед. Это кажется мне менее спорным, чем интерфейсы части 1 (проверка границ).
В целом, я не убежден в части 1 «Интерфейсы проверки границ». Материал в проекте части 2 «Функции динамического распределения» лучше.
Если бы это зависело от меня, я бы немного продвинулся по линии части 1, но я бы также пересмотрел интерфейсы в стандартной библиотеке C C99, которые возвращают char *
в начало строки (например, strcpy()
и strcat()
), чтобы вместо возврата указателя на начало они возвращали указатель на нулевой байт в конце новой строки. Это сделало бы некоторые общие идиомы (такие как многократные конкатенации строк в конце другой) более эффективными, поскольку это сделало бы тривиальным, чтобы избежать квадратичного поведения, демонстрируемого кодом, который многократно использует strcat()
. Все замены обеспечат нулевое завершение выходных строк, как это делают версии TR24731. Я не совсем против идеи проверки интерфейса и функций обработки исключений. Это сложное дело.
Реализация Microsoft отличается от стандартной спецификации
Обновление (2011-05-08)
Смотрите также этот вопрос . К сожалению, и, что крайне важно для полезности функций TR24731, определения некоторых функций различаются между реализацией Microsoft и стандартом, что делает их бесполезными (для меня). Мой ответ там цитирует vsnprintf_s()
.
Например, TR 24731-1 говорит, что интерфейс для vsnprintf_s()
:
#define __STDC_WANT_LIB_EXT1__ 1
#include <stdarg.h>
#include <stdio.h>
int vsnprintf_s(char * restrict s, rsize_t n,
const char * restrict format, va_list arg);
К сожалению, MSDN говорит, что интерфейс для vsnprintf_s()
:
int vsnprintf_s(
char *buffer,
size_t sizeOfBuffer,
size_t count,
const char *format,
va_list argptr
);
Параметры
- буфер - место хранения для вывода.
- sizeOfBuffer - Размер буфера для вывода.
- count - Максимальное количество символов для записи (не включая завершающий ноль) или _TRUNCATE.
- формат - Спецификация формата.
- argptr - указатель на список аргументов.
Обратите внимание, что это не просто вопрос отображения типов: число фиксированных аргументов различно и, следовательно, несовместимо. Мне также неясно (и, по-видимому, также и комитету по стандартам), какая польза от наличия обоих 'sizeOfBuffer' и 'count'; она выглядит как одна и та же информация дважды (или, по крайней мере, код обычно пишется с одинаковым значением для обоих параметров).
Точно так же существуют проблемы с scanf_s()
и его родственниками. Microsoft говорит, что тип параметра длины буфера - unsigned
(явно указывается «Параметр размера имеет тип unsigned
, а не size_t
»). Напротив, в Приложении K параметр размера имеет тип rsize_t
, который является ограниченным вариантом size_t
(rsize_t
является другим именем для size_t
, но RSIZE_MAX
меньше SIZE_MAX
). Итак, опять же, код, вызывающий scanf_s()
, должен был бы быть написан по-разному для Microsoft C и Standard C.
Первоначально я планировал использовать «безопасные» функции как способ заставить некоторый код корректно компилироваться как в Windows, так и в Unix, без необходимости писать условный код. Поскольку это побеждено, потому что функции Microsoft и ISO не всегда одинаковы, пора отказаться.
Изменения в Microsoft vsnprintf()
в Visual Studio 2015
В документации Visual Studio 2015 для vsnprintf()
отмечается, что интерфейс изменился:
Начиная с UCRT в Visual Studio 2015 и Windows 10, vsnprintf
больше не идентичен _vsnprintf
. Функция vsnprintf
соответствует стандарту C99; _vnsprintf
сохраняется для обратной совместимости.
Однако интерфейс Microsoft для vsnprintf_s()
не изменился.
Другие примеры различий между Microsoft и Приложением K
Стандартный вариант C11 localtime_s()
определен в ИСО / МЭК 9899: 2011 Приложение K.3.8.2.4 как:
struct tm *localtime_s(const time_t * restrict timer,
struct tm * restrict result);
по сравнению с MSDN-вариантом localtime_s()
, определенным как:
errno_t localtime_s(struct tm* _tm, const time_t *time);
и вариант POSIX localtime_r()
, определенный как:
struct tm *localtime_r(const time_t *restrict timer,
struct tm *restrict result);
Стандарт C11 и функции POSIX эквивалентны, кроме имени. Интерфейс Microsoft отличается по интерфейсу, хотя и имеет общее имя со стандартом C11.
Другим примером различий является Microsoft strtok_s()
и Приложение K strtok_s()
:
char *strtok_s(char *strToken, const char *strDelimit, char **context);
против
char *strtok_s(char * restrict s1, rsize_t * restrict s1max, const char * restrict s2, char ** restrict ptr);
Обратите внимание, что вариант Microsoft имеет 3 аргумента, тогда как вариант Приложения K имеет 4. Это означает, что список аргументов для strtok_s()
корпорации Майкрософт совместим с strtok_r()
POSIX - так что их вызовы эффективно взаимозаменяемы, если вы изменяете имя функции (например, макросом), но версия Standard C (Приложение K) отличается от версии с дополнительным аргументом.
Вопрос В различных декларациях qsort_r()
для Mac и Linux есть ответ, в котором также обсуждаются qsort_s()
, как определено Microsoft, и qsort_s()
, как определено TR24731-1 - опять же, интерфейсы отличается.
ISO / IEC 9899: 2011 - Стандарт C11
Стандарт C11 ( Проект на декабрь 2010 г. ; вы можете в одно время получить копию PDF окончательного стандарта ISO / IEC 9899: 2011 в интернет-магазине ANSI для 30 USD) имеет функции TR24731-1 в качестве дополнительной части стандарта. Они определены в Приложении K (Интерфейсы проверки границ), которое является «нормативным», а не «информационным», но является необязательным.
Стандарт C11 не имеет функций TR24731-2, что печально, потому что функция vasprintf()
и ее родственники могут быть действительно полезными.
Краткое резюме:
- C11 содержит TR24731-1
- C11 не содержит TR24731-2
- C18 - это то же самое, что и C11 w.r.t TR24731.
Предложение об исключении Приложения K из преемника C11
Дедупликатор указал в комментарии на другой вопрос о том, что есть предложение перед комитетом по стандарту ISO C (ISO / IEC JTC1 / SC22 / WG14)
Содержит ссылки на некоторые из существующих реализаций функций Приложения K - ни одна из них широко не используется (но вы можете найти их в документе, если вам интересно).
Документ заканчивается рекомендацией:
Таким образом, мы предлагаем исключить Приложение K из следующего пересмотра стандарта C или исключить его, а затем удалить.
Я поддерживаю эту рекомендацию.
Стандарт C18 не изменил статус Приложения K. Существует документ N2336 , в котором предлагается внести некоторые изменения в Приложение K, исправляя его дефекты, а не устраняя их полностью.