strerror_r неправильно объявлен в Alpine Linux

я использую strerror_r в функции помощника регистрации. Как описано в справочной странице, есть две версии этой функции. Версия POSIX возвращает int. Версия GNU возвращает строку (char *).

Таким образом, чтобы мой код 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

Похоже, что независимо от того, какая среда компилятора используется, единственной объявленной версией strerror_r является версия POSIX, которая возвращает int. Так что это объясняет, почему произошла ошибка.

Без необходимости сообщать пользователям, что они могут вручную #undef _GNU_SOURCE или измените источник, как я могу обойти это так, чтобы код продолжал быть переносимым? Глобально неопределенный _GNU_SOURCE, вероятно, не является стартовым, потому что это C ++ (и, как уже упоминалось выше, требуется libstdc ++). Я пытаюсь увидеть, будет ли другая макрокоманда, которую я смог бы проверить, но я не могу придумать ничего очевидного.

2

Решение

Вы можете воспользоваться перегрузкой функции C ++:

char* check_error(int result, char* buffer, int err) {
if(result)
sprintf(buffer, "unknown error: %d", err);
return buffer;
}

char* check_error(char* result, char*, int) {
return result;
}

И избавьтесь от условной компиляции в использовании:

char buffer[1000];
buffer[0] = '\0';
char* msg = check_error(strerror_r(err, buffer, sizeof buffer), buffer, err);
LogToFile(msg);
7

Другие решения

Других решений пока нет …

По вопросам рекламы ammmcru@yandex.ru
Adblock
detector