首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >为什么我不能使用strerror?

为什么我不能使用strerror?
EN

Stack Overflow用户
提问于 2009-05-22 22:56:08
回答 7查看 29.1K关注 0票数 35

我正在把一些代码移植到Windows上,微软的编译器(Visual C++ 8)告诉我strerror()是不安全的。

抛开来自微软的所有安全字符串的烦人因素,我实际上可以看到一些被弃用的函数是危险的。但我不明白strerror()会出什么问题。它接受一个代码(int),并返回相应的字符串,如果该代码未知,则返回空字符串。

危险在哪里?

在C中有没有好的替代方案?

在C++中有没有好的替代方案?

编辑

有了一些很好的答案,并且现在了解到一些实现可能疯狂到实际上写入公共共享缓冲区-在单线程内重入是不安全的,更不用说线程之间了!-我的问题不再是“为什么我不能使用它,还有什么替代方案?”到“在C和/或C++中有什么像样的、简洁的替代方案吗?”

提前感谢

EN

回答 7

Stack Overflow用户

回答已采纳

发布于 2009-05-22 23:02:43

strerror被弃用,因为它不是线程安全的。strerror在内部静态缓冲区上工作,该缓冲区可能会被其他并发线程覆盖。您应该使用一个名为strerror_s的安全变体。

安全变体要求将缓冲区大小传递给函数,以便在写入缓冲区之前验证缓冲区是否足够大,从而帮助避免可能允许恶意代码执行的缓冲区溢出。

票数 31
EN

Stack Overflow用户

发布于 2009-05-22 23:27:21

strerror本身并不是不安全的。在过去,在线程化之前,这根本不是问题。使用线程,两个或多个线程可以调用strerror,从而使返回的缓冲区处于未定义的状态。对于单线程程序,使用strerror应该没什么坏处,除非他们在libc中玩一些奇怪的游戏,比如一个DLL中所有应用程序的公共内存。

为了解决这个问题,有一个新的接口来实现相同的功能:

代码语言:javascript
复制
int strerror_r(int errnum, char *buf, size_t buflen);

请注意,调用方提供缓冲区空间和缓冲区大小。这就解决了问题。即使对于单线程应用程序,您也可以使用它。它不会有一点伤害,你也可以习惯用更安全的方式来做。

注意:上面的原型来自strerror_r()的POSIX规范。它可能因平台或编译器选项或#define符号的不同而不同。例如,GNU根据#define提供该版本或他们自己的版本。

票数 23
EN

Stack Overflow用户

发布于 2009-05-23 10:59:52

已经有了一些很好的答案,并且现在了解到一些实现可能疯狂到实际上写入公共共享缓冲区-在单线程内重入是不安全的,更不用说线程之间了!-我的问题不再是“为什么我不能使用它,还有什么替代方案?”到“在C和/或C++中有什么像样的、简洁的替代方案吗?”

Posix指定了strerror_r(),在Windows上可以使用strerror_s(),虽然略有不同,但具有相同的目标。我这样做:

代码语言:javascript
复制
#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之外的错误代码,并显示一些调试信息。您可以根据需要对其进行调整。

票数 17
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/900338

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档