Отсутствует функция C11 strerrorlen_s под MSVC 2017
Я пытаюсь найти заголовок для включения strerrorlen_s
функция от стандарта C11 под MSVC 2017. Мне это нужно для выделения места для сообщения об ошибке, чтобы получить с strerror_s
, Код следующий:
auto size = strerrorlen_s(errno) + 1;
char* errorReason = (char*)alloca(size);
strerror_s(errorReason, size, errno);
std::ostringstream oss;
oss << "Cannot open: " << fileName << " Reason: " << errorReason;
throw std::runtime_error(oss.str());
В документации есть следующие слова:
Как и для всех функций с проверкой границ, strerror_s и strerrorlen_s гарантированно будут доступны только в том случае, если
__STDC_LIB_EXT1__
определяется реализацией, и если пользователь определяет__STDC_WANT_LIB_EXT1__
к целочисленной константе1
перед включениемstring.h
,
MSVC 2017 не определяет __STDC_LIB_EXT1__
и кажется, что определяющий __STDC_WANT_LIB_EXT1__
перед включением string.h
не имеет эффекта Хотя strerror_s
доступен.
- Является
strerrorlen_s
доступно под Windows с MSVC 2017? - Можно ли каким-то другим способом получить длину сообщения об ошибке, если функция недоступна?
- Является
strerror_s
Потокобезопасен в Windows, потому что кажется, что в Linux это не так, и strerror_r должен использоваться, если есть необходимость в безопасности потоков, но он не доступен в Windows?
1 ответ
Microsoft Visual Studio, когда он используется в качестве компилятора C, в основном соответствует версии стандарта C 1990 года. Недавно были предприняты некоторые попытки обновить его до версии 1999 года. Они все еще сильно отстают в этом - компилятор не приближается к версии 2011 года. Если вам нужен стандартный совместимый компилятор C, вы не можете использовать VS.
Кроме того, вы, похоже, используете компилятор в режиме C++, который не совсем помогает соответствию стандарту C... C11 и C++11 не всегда совместимы.
При этом функция, которую вы запрашиваете, является частью необязательного интерфейса проверки границ, который, я считаю, очень немногие, если таковые вообще имеются, компиляторы еще не реализовали. Некоторые функции, присутствующие в интерфейсе проверки границ, существовали в VS до C11 как нестандартные расширения. Они не обязательно соответствуют стандарту.
Нет никаких гарантий, что библиотечные функции являются реентерабельными. Они могут быть или не быть потокобезопасными.
Вы можете найти реализацию здесь: SafeClib Рейни Урбан
// Safe C Library
//
// Copyright (C) 2012, 2013 Cisco Systems
// Copyright (C) 2017 Reini Urban
// All rights reserved.
//
// Permission is hereby granted, free of charge, to any person
// obtaining a copy of this software and associated documentation
// files (the "Software"), to deal in the Software without
// restriction, including without limitation the rights to use,
// copy, modify, merge, publish, distribute, sublicense, and/or
// sell copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following
// conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
// OTHER DEALINGS IN THE SOFTWARE.
size_t strerrorlen_s(errno_t errnum)
{
#ifndef ESNULLP
#define ESNULLP ( 400 ) /* null ptr */
#endif
#ifndef ESLEWRNG
#define ESLEWRNG ( 410 ) /* wrong size */
#endif
#ifndef ESLAST
#define ESLAST ESLEWRNG
#endif
static const int len_errmsgs_s[] = {
sizeof "null ptr", /* ESNULLP */
sizeof "length is zero", /* ESZEROL */
sizeof "length is below min", /* ESLEMIN */
sizeof "length exceeds RSIZE_MAX",/* ESLEMAX */
sizeof "overlap undefined", /* ESOVRLP */
sizeof "empty string", /* ESEMPTY */
sizeof "not enough space", /* ESNOSPC */
sizeof "unterminated string", /* ESUNTERM */
sizeof "no difference", /* ESNODIFF */
sizeof "not found", /* ESNOTFND */
sizeof "wrong size", /* ESLEWRNG */
};
if (errnum >= ESNULLP && errnum <= ESLAST)
{
return len_errmsgs_s[errnum - ESNULLP] - 1;
}
else
{
const char *buf = strerror(errnum);
return buf ? strlen(buf) : 0;
}
}