Я использую strerror_r в функции вспомогательного каротажа. Как описывает справочная страница, существуют две версии этой функции. Версия POSIX возвращает int. Версия GNU возвращает строку (char *).strerror_r неверно объявлено в Alpine Linux
Как таковой, так что мой C++ код более компактен, у меня есть блок кода, подобный этому:
char buffer[1000];
int size = 1000;
int result = 0;
char* msg = buffer;
buffer[0] = '\0';
#ifdef _GNU_SOURCE
msg = strerror_r(err, buffer, size);
#else
result = strerror_r(err, buffer, size);
if (result != 0)
{
sprintf(buffer, "unknown error: %d", err);
}
#endif
LogToFile(msg);
В приведенном выше коде блок, он будет использовать либо версию strerror_r
в зависимости от наличия из _GNU_SOURCE
, который ВСЕГДА установлен g ++, потому что это требует libstdC++. На Mac и других вариантах Unix он будет использовать версию POSIX.
Теперь этот код работает хорошо уже до сегодняшнего дня. Пользователь пытается скомпилировать свой код на Alpine Linux и сообщил эту ошибку компилятора сегодня на линии с помощью strerror_r
main.cpp:16:21 error: invalid conversion from 'int' to 'char*' [-fpermissive]
который отображает на этой линии:
#ifdef _GNU_SOURCE
msg = strerror_r(err, buffer, size);
Привлекательность пика в /usr/include/string.h
на этой платформе показывает следующее:
#if defined(_POSIX_SOURCE) || defined(_POSIX_C_SOURCE) \
|| defined(_XOPEN_SOURCE) || defined(_GNU_SOURCE) \
|| defined(_BSD_SOURCE)
...
int strerror_r (int, char *, size_t);
...
#endif
Который, кажется, что независимо от того, какая среда компилятора используется, единственная заявленная версия n strerror_r - это версия POSIX, которая возвращает int. Поэтому объясняется, почему произошла ошибка.
Не указывая пользователям, что они могут вручную #undef _GNU_SOURCE
или изменить источник, как я могу обойти это, чтобы код мог оставаться портативным? Глобальная неопределенность _GNU_SOURCE скорее всего не стартер, потому что это C++ (и, как упоминалось выше, требуется libstdC++). Я пытаюсь понять, будет ли еще одна комбинация макросов, на которую я мог бы протестировать, но я не могу придумать ничего очевидного.
Официальной макро проверки (по справочной странице Вы связываетесь) является '(_POSIX_C_SOURCE> = 200112L || _XOPEN_SOURCE> = 600) &&! _GNU_SOURCE', чтобы быть правдой, если предоставляется версия POSIX, иначе предоставляется версия GNU. Это означает, что ваш чек должен быть достаточным, чтобы обеспечить версию GNU, а библиотека C в Alpine Linux, похоже, глючит или устарела. –
Оберните его в свою собственную функцию. Сделайте его достаточно гибким, чтобы использовать любой вариант. –
@ н.м. Можете ли вы уточнить? Это уже завернуто в функцию ... – selbie