Пряма відповідь на питання
Мені подобається відповідь Роберта, але я також маю кілька поглядів на питання, які я порушив.
Чи використовуєте ви бібліотеку або компілятор з підтримкою функцій TR24731-1?
Ні, ні.
Якщо так, то який компілятор чи бібліотека та на якій платформі?
Я вважаю, що функції надає MS Visual Studio (наприклад, MS VC ++ 2008 Edition), і є застереження, які заохочують вас їх використовувати.
Ви виявили помилки в результаті виправлення коду для використання цих функцій?
Ще ні. І я не сподіваюся розкрити багато в моєму коді. Деякий інший код, з яким я працюю - можливо. Але я ще не переконаний.
Які функції надають найбільше значення?
Мені подобається той факт, що сімейство функцій printf_s () не приймає %n
специфікатор формату ' '.
Чи є такі, що не надають значення або від’ємного значення?
Функції tmpfile_s()
and tmpnam_s()
викликають жахливе розчарування. Їм справді потрібно було працювати більше якmkstemp()
який як створює файл, так і відкриває його, щоб переконатися у відсутності вразливості TOCTOU (час перевірки, час використання). По суті, ці два дають дуже мало цінності.
Я також думаю, що це strerrorlen_s()
забезпечує дуже мало цінності.
Чи плануєте Ви використовувати бібліотеку в майбутньому?
Я в двох думках про це. Я розпочав роботу над бібліотекою, яка реалізовувала б можливості TR 24731 у порівнянні зі стандартною бібліотекою C, але мене вловлював обсяг модульного тестування, необхідний, щоб продемонструвати, що вона працює правильно. Я не впевнений, чи продовжувати це. У мене є якийсь код, який я хочу перенести на Windows (головним чином, через збочене бажання надати підтримку на всіх платформах - це працює над похідними Unix вже пару десятиліть). На жаль, щоб змусити його компілюватись без попереджень компіляторів MSVC, мені доводиться обмазувати код речами, щоб уникнути, щоб MSVC не засмучував мене, використовуючи цілком надійні (при обережному використанні) стандартні функції бібліотеки C. І це не апетитно. Досить погано, що мені доводиться мати справу з більшістю системи, яка склалася за цей період на два десятки років; доводиться мати справу з чиєюсь ідеєю розваги (змусити людей прийняти TR 24731, коли їм це не потрібно) дратує. Саме тому я почав розробку бібліотеки - щоб дозволити мені використовувати однакові інтерфейси на Unix та Windows. Але я не впевнений, що звідси буду робити.
Ви взагалі відстежуєте роботу TR24731-2?
Я не відстежував його, поки не перейшов на сайт стандартів під час збору даних для запитання. Функції asprintf()
and vasprintf()
імовірно цінні; Я б їх використав. Я не впевнений у функціях вводу-виводу потоку пам'яті. Після strdup()
нормується на рівні C було б величезним кроком вперед. Мені це здається менш суперечливим, ніж інтерфейси частини 1 (перевірка меж).
Загалом, я не впевнений у частині 1 «Інтерфейси перевірки обмежень». Матеріал у проекті частини 2 "Функції динамічного розподілу" є кращим.
Якби це залежало від мене, я б рухався дещо по лініях частини 1, але я також переглянув інтерфейси в стандартній бібліотеці C99 C, які повертають a char *
до початку рядка (наприклад, strcpy()
і strcat()
), щоб замість повертаючи вказівник на початок, вони повертали вказівник на нульовий байт в кінці нового рядка. Це зробило б деякі загальні ідіоми (наприклад, неодноразове об'єднання рядків у кінець іншої) більш ефективними, оскільки це зробило б тривіальним уникнення квадратичної поведінки коду, який неодноразово використовується strcat()
. Усі заміни забезпечать припинення вихідних рядків, як у версіях TR24731. Я не зовсім не люблю ні ідею перевірки інтерфейсу, ні функції обробки винятків. Це складна справа.
Реалізація корпорації Майкрософт відрізняється від стандартної специфікації
Оновлення (08.05.2011)
Дивіться також це питання . На жаль і фатально для корисності функцій 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 - Максимальна кількість символів для запису (не враховуючи закінчувальне null) або _TRUNCATE.
- формат - специфікація формату.
- argptr - вказівник на список аргументів.
Зауважте, що це не просто питання зіставлення типів: кількість фіксованих аргументів різна і, отже, непримирна. Мені також незрозуміло (і, мабуть, також комітету зі стандартів), яка користь від наявності "sizeOfBuffer" і "count"; схоже, двічі одна і та ж інформація (або, принаймні, код зазвичай пишеться з однаковим значенням для обох параметрів).
Подібним чином є також проблеми з scanf_s()
та його родичами. Корпорація Майкрософт каже, що тип параметра довжини буфера є unsigned
(явно вказуючи "Параметр розміру має тип unsigned
, а не size_t
"). На відміну від цього, у Додатку К параметр розміру має тип 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
Стандартний варіант С11 localtime_s()
визначений у ISO / IEC 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 s » strtok_s()
і додаток К - х 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 аргументи, тоді як варіант Додатку К - 4. Це означає, що список аргументів для Microsoft strtok_s()
сумісний з POSIXstrtok_r()
- тому виклики до них ефективно взаємозамінні, якщо ви зміните назву функції (наприклад, за допомогою макросу) - але версія стандарту С (Додаток К) відрізняється від обох додатковим аргументом.
Питання Різні декларації qsort_r()
на Mac і Linux мають відповідь, яка також обговорює, qsort_s()
як визначено Microsoft і qsort_s()
як визначено TR24731-1 - знову ж таки, інтерфейси різні.
ISO / IEC 9899: 2011 - Стандарт С11
Стандарт C11 ( проект грудня 2010 року ; ви могли свого часу отримати копію остаточного стандарту ISO / IEC 9899: 2011 у веб-магазині ANSI за 30 доларів США), як додаткові функції TR24731-1 частина стандарту. Вони визначені в Додатку К (Інтерфейси перевірки обмежень), який є "нормативним", а не "інформаційним", але є необов'язковим.
Стандарт C11 не має в собі функцій TR24731-2 - що прикро, оскільки vasprintf()
функція та її родичі можуть бути справді корисними.
Короткий підсумок:
- C11 містить TR24731-1
- C11 не містить TR24731-2
- C18 те саме, що C11 wrt TR24731.
Пропозиція вилучити Додаток К із наступника С11
Дедулікатор в коментарі до іншого питання зазначив, що є пропозиція перед комітетом зі стандартів ISO C (ISO / IEC JTC1 / SC22 / WG14)
Він містить посилання на деякі з існуючих реалізацій функцій Додатку К - жодна з них не використовується широко (але ви можете знайти їх у документі, якщо вам цікаво).
Документ закінчується рекомендацією:
Тому ми пропонуємо, щоб Додаток К або був вилучений із наступного перегляду стандарту С, або припинений, а потім видалений.
Я підтримую цю рекомендацію.
Стандарт С18 не змінив статусу Додатку К. Існує стаття N2336, яка виступає за внесення деяких змін до Додатку К, виправлення його дефектів, а не його взагалі видалення.
strlen()
до коду". Безумовно, бувають випадки, колиstrlen()
не правильна відповідь, наприклад, при передачі буфера функції вводу-виводу (наприкладgets_s()
). Але, можливо, ви можете детальніше розказати про те, про що думаєте?