Альтернативы MS strncpy_s

Каковы некоторые альтернативы расширенным функциям безопасности Microsoft, таким как strncpy_s или _itoa_s? Хотя разработка в среде MS является задачей написания кода, который легко переносится на другие платформы.

Ответ 1

Ярость правильная, за ней нет сложной логики.

Я бы просто использовал версию Microsoft на данный момент, и если вы решите позже перейти на другую ОС, THEN внедрите ее самостоятельно для целевой платформы и используйте команды препроцессора, чтобы указать вашу реализацию на платформах, отличных от Windows.

Ответ 2

std::string s(Cstring, n);

Ответ 3

Если вы действительно хотите запрограммировать в C:

Используйте простой старый стандарт strncpy.

Если вы программируете на С++:

Используйте простой стандартный класс строк std::string.

(подсказка: вы, вероятно, захотите последнего. Строки C - это просто ошибки, ожидающие своего появления, даже если вы используете "безопасные" функции *_s. С++ добавил класс строк по какой-то причине)

Ответ 4

Попробуйте strlcpy. Хотя он и не является стандартным C, он существует на нескольких платформах, и вы можете загружать реализации, поскольку исходный код доступен бесплатно. См. http://www.gratisoft.us/todd/papers/strlcpy.html

Ответ 5

Просто используйте strncpy и отключите предупреждение в VС++.

Ответ 6

Насколько я понимаю, strncpy_s не имеет сложной логики: просто берет минимум длины строки, размеры источника и места назначения и копирует итоговое количество символов в пункт назначения. Если вам это нужно, почему бы не реализовать его самостоятельно?

Ответ 7

Вам может быть интересен проект Apache Portable Runtime:

Миссия проекта Apache Portable Runtime (APR) заключается в создании и обслуживании программных библиотек, которые обеспечивают предсказуемый и последовательный интерфейс для базовых реализаций платформы.

autoconf также может позаботиться о некоторых из этих различий в конкретной платформе (установив #defines и т.д.), хотя мой опыт работы с ним под Windows оставляет желать лучшего.

Ответ 8

Я думаю, @codeLizard спрашивает о том, как написать совместимый код для обработки всех функций, которые Microsoft устарела в пользу своих безопасных версий, а не только строковых функций.

Функции, основанные на защищенных функциях Microsoft, включены в приложение К стандарта C11, но приложение не поддерживается широко за пределами MSVS.

Вы можете писать макросы и встроенные функции в файле include для сопоставления между традиционными и безопасными версиями. Я разместил набор макросов преобразования здесь. Если вы хотите скопировать их, получите их с любимой страницы; более полные, лучшие комментарии, чем ниже.

Однако этот подход не работает для сопоставления традиционных функций с безопасными версиями, которые принимают аргументы размера, если аргументы размера также не присутствуют в традиционных функциях. Кроме того, защищенные функции различаются по типу исключений, а иногда и в возвращаемых значениях. Мои текущие преобразования не учитывают этого. Когда у меня будет время, я попытаюсь улучшить их, где я могу это сделать. Тем временем я оставлю это упражнение для читателя.

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

Ниже приведена сокращенная версия вышеописанного подхода к макро/встроенной функции:

#pragma once
#if !defined(FCN_S_MACROS_H)
   #define   FCN_S_MACROS_H
   #include <cstdio>
   #include <string> // Need this for _stricmp
   using namespace std;

   #if (defined(_MSC_VER) && (_MSC_VER >= 1400) ) // _MSC_VER==MSVC 2005 

      // The function plus macro strategy could be used to maintain
      // consistent exception behaviors and return values. 
      inline extern
      FILE*   fcnSMacro_fopen_s(char *fname, char *mode)
      {  FILE *fptr;
         fopen_s(&fptr, fname, mode);
         return fptr;
      }
      #define fopen(fname, mode)               fcnSMacro_fopen_s((fname), mode))

      #define fprintf(fptr, ...)               fprintf_s((fptr), __VA_ARGS__)
      #define fscanf                           fscanf_s
      #define strncpy(dest, source, count)     strcpy_s((dest), (count), (source))
      // Can't map sprinf to sprintf_s (size argument unavailable). 
      //    #define sprintf                    ???


      ...
    #else
      #define fopen_s(fp, fmt, mode)          *(fp)=fopen( (fmt), (mode))
      #define fprintf_s                        fprintf
      #define fscanf_s                         fscanf
      #define strcpy_s(dest, count, source)    strncpy( (dest), (source), (count) )
      ...
    #endif //_MSC_VER
#endif // FCN_S_MACROS_H

Ответ 9

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

Ответ 10

Да, попробуйте https://rurban.github.io/safeclib/.

Это независимая от платформы реализация C11 Annex K поверх всех libc. Он в основном совместим с Windows sec_api. Windows немного отклоняется от спецификации с некоторыми функциями.

strncpy_s является одним из самых сложных API в sec_api. Windows не обнаруживает переполнение двух длин, а не перекрытие двух строк. И что делать, если 4-й аргумент count = 0 также сомнительный. Спецификация http://en.cppreference.com/w/c/string/byte/strncpy говорит, что значение с нулевым возвратом подразумевает... что результат в s1 завершен нулем, но в окнах это неправильно. Он просто прерывается слишком рано. См. реализация вина: https://github.com/mirror/reactos/blob/master/reactos/lib/sdk/crt/wine/heap.c#L577

И для защищенного суффикса _s следует предположить, что ошибочно скопированные байты в буфер назначения очищаются от любопытных глаз при возникновении ошибки времени выполнения. Не так в Windows с их sec_api. Они просто устанавливают самый первый байт в 0.

https://github.com/rurban/safeclib/releases