Если вы храните свои сессии в БД, то
rake db:sessions:clear
strerror
устарел, поскольку он не является потокобезопасным. strerror
работает с внутренним статическим буфером, который может быть перезаписан другими параллельными потоками. Вы должны использовать безопасный вариант под названием strerror_s
.
Безопасный вариант требует, чтобы размер буфера был передан функции, чтобы проверить, достаточно ли большой буфер перед записью в него, что помогает избежать буфера переполнения, которые могут позволить выполнить вредоносный код.
Получив несколько хороших ответов и теперь понимая, что некоторые реализации могут быть достаточно сумасшедшими, чтобы на самом деле писать в общий разделяемый буфер - небезопасно для повторного входа в одном потоке, не говоря уже о между потоками! - мой вопрос перестает быть «Почему я не могу его использовать и какие есть альтернативы?» на «Есть ли достойные, сжатые альтернативы в C и / или C ++?»
Posix указывает strerror_r ()
, а в Windows вы можете использовать strerror_s ()
, что является немного отличается, но преследует ту же цель. Я делаю это:
#define BAS_PERROR(msg, err_code)\
bas_perror(msg, err_code, __FILE__, __LINE__)
void bas_perror (const char* msg, int err_code, const char* filename,
unsigned long line_number);
void
bas_perror (const char* usr_msg, int err_code, const char* filename,
unsigned long line_number)
{
char sys_msg[64];
#ifdef _WIN32
if ( strerror_s(sys_msg, sizeof sys_msg, err_code) != 0 )
{
strncpy(sys_msg, "Unknown error", taille);
sys_msg[sizeof sys_msg - 1] = '\0';
}
#else
if ( strerror_r(err_code, sys_msg, sizeof sys_msg) != 0 )
{
strncpy(sys_msg, "Unknown error", sizeof sys_msg);
sys_msg[sizeof sys_msg - 1] = '\0';
}
#endif
fprintf(stderr, "%s: %s (debug information: file %s, at line %lu)\n",
usr_msg, sys_msg, filename, line_number);
}
Я написал эту функцию, потому что функции потоков Posix не t изменить errno
, вместо этого они возвращают код ошибки. Таким образом, эта функция в основном аналогична perror ()
, за исключением того, что она позволяет указать код ошибки, отличный от errno
, а также отображает некоторую отладочную информацию. Вы можете адаптировать его под свои нужды.
strerror
сам по себе небезопасен. Раньше, до создания потоков, это не было проблемой. С потоками два или более потока могут вызвать strerror
, оставляя возвращенный буфер в неопределенном состоянии. Для однопоточных программ не повредит использовать strerror
, если только они не играют в какие-то странные игры в libc, такие как общая память для всех приложений в DLL.
Для решения этой проблемы есть новый интерфейс. та же функциональность:
int strerror_r(int errnum, char *buf, size_t buflen);
Обратите внимание, что вызывающая сторона предоставляет буферное пространство и размер буфера. Это решает проблему. Вы можете использовать его даже для однопоточных приложений. Это нисколько не повредит, и вы можете привыкнуть делать это более безопасным способом.
ПРИМЕЧАНИЕ: приведенный выше прототип является спецификацией XSI. Он может варьироваться в зависимости от платформы, параметров компилятора или символов #define
. GNU, например, делает эту или их собственную версию доступной в зависимости от #define
Нельзя полагаться на строку, возвращаемую strerror ()
, потому что она может измениться при следующем вызове функции. В этом случае возвращенные ранее значения могут стать устаревшими. Особенно в многопоточных средах вы не можете гарантировать, что строка действительна при доступе к ней.
Представьте себе это:
Thread #1:
char * error = strerror(1);
Thread #2
char * error = strerror(2);
printf(error);
В зависимости от реализации strerror ()
, этот код выводит код ошибки для кода ошибки 2, а не для кода ошибки 1.
Для сжатой оболочки вы можете использовать STLSoft stlsoft :: error_desc
, например:
std::string errstr = stlsoft::error_desc(errno);
Глядя на код, он Кажется, что он реализован в терминах strerror ()
, что означает, что он будет безопасным для повторного входа в поток (то есть при многократном использовании в данном операторе), но он не решает проблему многопоточности.
Кажется, у них довольно быстрые циклы выпуска дефектов, так что вы можете попробовать запросить мод?
Хотя я не знаю причин Microsoft, я отмечаю, что strerror возвращает неконстантный символ *, что означает, что существует риск того, что какой-то веселый шутник вызвал strerror до того, как вы это сделали и изменили сообщение.