我正在把一些代码移植到Windows上,微软的编译器(Visual C++ 8)告诉我strerror()是不安全的。
抛开来自微软的所有安全字符串的烦人因素,我实际上可以看到一些被弃用的函数是危险的。但我不明白strerror()会出什么问题。它接受一个代码(int),并返回相应的字符串,如果该代码未知,则返回空字符串。
危险在哪里?
在C中有没有好的替代方案?
在C++中有没有好的替代方案?
编辑
有了一些很好的答案,并且现在了解到一些实现可能疯狂到实际上写入公共共享缓冲区-在单线程内重入是不安全的,更不用说线程之间了!-我的问题不再是“为什么我不能使用它,还有什么替代方案?”到“在C和/或C++中有什么像样的、简洁的替代方案吗?”
提前感谢
发布于 2009-05-22 23:02:43
strerror被弃用,因为它不是线程安全的。strerror在内部静态缓冲区上工作,该缓冲区可能会被其他并发线程覆盖。您应该使用一个名为strerror_s的安全变体。
安全变体要求将缓冲区大小传递给函数,以便在写入缓冲区之前验证缓冲区是否足够大,从而帮助避免可能允许恶意代码执行的缓冲区溢出。
发布于 2009-05-22 23:27:21
strerror本身并不是不安全的。在过去,在线程化之前,这根本不是问题。使用线程,两个或多个线程可以调用strerror,从而使返回的缓冲区处于未定义的状态。对于单线程程序,使用strerror应该没什么坏处,除非他们在libc中玩一些奇怪的游戏,比如一个DLL中所有应用程序的公共内存。
为了解决这个问题,有一个新的接口来实现相同的功能:
int strerror_r(int errnum, char *buf, size_t buflen);请注意,调用方提供缓冲区空间和缓冲区大小。这就解决了问题。即使对于单线程应用程序,您也可以使用它。它不会有一点伤害,你也可以习惯用更安全的方式来做。
注意:上面的原型来自strerror_r()的POSIX规范。它可能因平台或编译器选项或#define符号的不同而不同。例如,GNU根据#define提供该版本或他们自己的版本。
发布于 2009-05-23 10:59:52
已经有了一些很好的答案,并且现在了解到一些实现可能疯狂到实际上写入公共共享缓冲区-在单线程内重入是不安全的,更不用说线程之间了!-我的问题不再是“为什么我不能使用它,还有什么替代方案?”到“在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线程函数并不修改errno,而是返回一个错误代码。因此,此函数与perror()基本相同,只是它允许您提供除errno之外的错误代码,并显示一些调试信息。您可以根据需要对其进行调整。
https://stackoverflow.com/questions/900338
复制相似问题