C 在可能的多线程环境中没有错误描述

C 在可能的多线程环境中没有错误描述,c,linux,multithreading,C,Linux,Multithreading,这些函数很奇怪。为什么我不能简单地获取一个指向字符串文本(constchar*)的指针,然后使用它呢 为什么要乱搞一个隐藏的静态缓冲区,它会给线程和信号带来问题,或者是用户分配的缓冲区,因为你不知道,手册页也不会告诉你,所以你猜一个好的大小是多少 有什么我没有得到的吗? 直截了当的线程有什么不相关的strerror实现,例如: #include <errno.h> #define E(n,s) case n: return s; const char* strerror(int n)

这些函数很奇怪。为什么我不能简单地获取一个指向字符串文本(
constchar*
)的指针,然后使用它呢

为什么要乱搞一个隐藏的静态缓冲区,它会给线程和信号带来问题,或者是用户分配的缓冲区,因为你不知道,手册页也不会告诉你,所以你猜一个好的大小是多少

有什么我没有得到的吗? 直截了当的线程有什么不相关的
strerror
实现,例如:

#include <errno.h>
#define E(n,s) case n: return s;
const char* strerror(int n){
  switch(n){
    //stole these messages from libc
    E(EILSEQ,       "Illegal byte sequence")
    E(EDOM,         "Domain error")
    E(ERANGE,       "Result not representable")

    E(ENOTTY,       "Not a tty")
    E(EACCES,       "Permission denied")
    E(EPERM,        "Operation not permitted")
    E(ENOENT,       "No such file or directory")
    E(ESRCH,        "No such process")
    E(EEXIST,       "File exists")

    E(EOVERFLOW,    "Value too large for data type")
    E(ENOSPC,       "No space left on device")
    E(ENOMEM,       "Out of memory")

    E(EBUSY,        "Resource busy")
    E(EINTR,        "Interrupted system call")
    E(EAGAIN,       "Resource temporarily unavailable")
    E(ESPIPE,       "Invalid seek")

    E(EXDEV,        "Cross-device link")
    E(EROFS,        "Read-only file system")
    E(ENOTEMPTY,    "Directory not empty")

    E(ECONNRESET,   "Connection reset by peer")
    E(ETIMEDOUT,    "Operation timed out")
    E(ECONNREFUSED, "Connection refused")
    E(EHOSTDOWN,    "Host is down")
    E(EHOSTUNREACH, "Host is unreachable")
    E(EADDRINUSE,   "Address in use")

    E(EPIPE,        "Broken pipe")
    E(EIO,          "I/O error")
    E(ENXIO,        "No such device or address")
    E(ENOTBLK,      "Block device required")
    E(ENODEV,       "No such device")
    E(ENOTDIR,      "Not a directory")
    E(EISDIR,       "Is a directory")
    E(ETXTBSY,      "Text file busy")
    E(ENOEXEC,      "Exec format error")

    E(EINVAL,       "Invalid argument")

    E(E2BIG,        "Argument list too long")
    E(ELOOP,        "Symbolic link loop")
    E(ENAMETOOLONG, "Filename too long")
    E(ENFILE,       "Too many open files in system")
    E(EMFILE,       "No file descriptors available")
    E(EBADF,        "Bad file descriptor")
    E(ECHILD,       "No child process")
    E(EFAULT,       "Bad address")
    E(EFBIG,        "File too large")
    E(EMLINK,       "Too many links")
    E(ENOLCK,       "No locks available")

    E(EDEADLK,      "Resource deadlock would occur")
    E(ENOTRECOVERABLE, "State not recoverable")
    E(EOWNERDEAD,   "Previous owner died")
    E(ECANCELED,    "Operation canceled")
    E(ENOSYS,       "Function not implemented")
    E(ENOMSG,       "No message of desired type")
    E(EIDRM,        "Identifier removed")
    E(ENOSTR,       "Device not a stream")
    E(ENODATA,      "No data available")
    E(ETIME,        "Device timeout")
    E(ENOSR,        "Out of streams resources")
    E(ENOLINK,      "Link has been severed")
    E(EPROTO,       "Protocol error")
    E(EBADMSG,      "Bad message")
    E(EBADFD,       "File descriptor in bad state")
    E(ENOTSOCK,     "Not a socket")
    E(EDESTADDRREQ, "Destination address required")
    E(EMSGSIZE,     "Message too large")
    E(EPROTOTYPE,   "Protocol wrong type for socket")
    E(ENOPROTOOPT,  "Protocol not available")
    E(EPROTONOSUPPORT,"Protocol not supported")
    E(ESOCKTNOSUPPORT,"Socket type not supported")
    E(ENOTSUP,      "Not supported")
    E(EPFNOSUPPORT, "Protocol family not supported")
    E(EAFNOSUPPORT, "Address family not supported by protocol")
    E(EADDRNOTAVAIL,"Address not available")
    E(ENETDOWN,     "Network is down")
    E(ENETUNREACH,  "Network unreachable")
    E(ENETRESET,    "Connection reset by network")
    E(ECONNABORTED, "Connection aborted")
    E(ENOBUFS,      "No buffer space available")
    E(EISCONN,      "Socket is connected")
    E(ENOTCONN,     "Socket not connected")
    E(ESHUTDOWN,    "Cannot send after socket shutdown")
    E(EALREADY,     "Operation already in progress")
    E(EINPROGRESS,  "Operation in progress")
    E(ESTALE,       "Stale file handle")
    E(EREMOTEIO,    "Remote I/O error")
    E(EDQUOT,       "Quota exceeded")
    E(ENOMEDIUM,    "No medium found")
    E(EMEDIUMTYPE,  "Wrong medium type")
    E(0,            "No error information")
  }
  return "";
}
#undef E
#包括
#定义E(n,s)情况n:返回s;
常量字符*strerror(整数n){
开关(n){
//从libc窃取了这些消息
E(EILSEQ,“非法字节序列”)
E(以东,“域错误”)
E(ERANGE,“结果不可代表”)
E(ENOTTY,“非tty”)
E(EACCES,“拒绝许可”)
E(EPERM,“不允许操作”)
E(enoint,“无此类文件或目录”)
E(ESRCH,“无此类流程”)
E(EEXIST,“文件存在”)
E(EOVERFLOW,“数据类型的值太大”)
E(ENOSPC,“设备上没有剩余空间”)
E(ENOMEM,“内存不足”)
E(EBUSY,“资源繁忙”)
E(EINTR,“中断的系统调用”)
E(EAGAIN,“资源暂时不可用”)
E(电子管道,“无效搜索”)
E(EXDEV,“跨设备链接”)
E(EROFS,“只读文件系统”)
E(enotery,“目录不为空”)
E(EconReset,“对等方重置连接”)
E(ETIMEDOUT,“操作超时”)
E(ECONREFUSE,“连接被拒绝”)
E(EHOSTDOWN,“主机已关闭”)
E(EHOSTUNREACH,“无法访问主机”)
E(使用中的地址)
E(EPIPE,“断管”)
E(EIO,“I/O错误”)
E(ENXIO,“无此类设备或地址”)
E(ENOTBLK,“需要闭锁装置”)
E(ENODEV,“无此类装置”)
E(ENOTDIR,“非目录”)
E(EISDIR,“是一个目录”)
E(ETXTBSY,“文本文件忙”)
E(ENOEXEC,“Exec格式错误”)
E(EINVAL,“无效参数”)
E(E2BIG,“参数列表太长”)
E(ELOOP,“符号链接循环”)
E(搪瓷名称,“文件名太长”)
E(ENFILE,“系统中打开的文件太多”)
E(EMFILE,“没有可用的文件描述符”)
E(EBADF,“错误的文件描述符”)
E(ECHILD,“无子进程”)
E(默认值,“错误地址”)
E(EFBIG,“文件太大”)
E(EMLINK,“链接过多”)
E(ENOLCK,“无可用锁”)
E(EDEADLK,“将发生资源死锁”)
E(ENOTRECOVERABLE,“状态不可恢复”)
E(EOWNERDEAD,“前所有者死亡”)
E(取消“操作已取消”)
E(ENOSYS,“功能未实现”)
E(Enomg,“无所需类型的消息”)
E(EIDRM,“删除标识符”)
E(ENOSTR,“设备不是流”)
E(ENODATA,“无可用数据”)
E(时间,“设备超时”)
E(ENOSR,“流外资源”)
E(ENOLINK,“链接已断开”)
E(EPROTO,“协议错误”)
E(EBADMG,“坏消息”)
E(EBADFD,“处于错误状态的文件描述符”)
E(ENOTSOCK,“非插座”)
E(EDESTADDRREQ,“需要目标地址”)
E(EMSGSIZE,“消息太大”)
E(EPROTOTYPE,“套接字的协议类型错误”)
E(InProtoop,“协议不可用”)
E(EPROTONOSUPPORT,“不支持协议”)
E(ESOCKTNOSUPPORT,“不支持插座类型”)
E(ENOTSUP,“不受支持”)
E(EPFNOSUPPORT,“不支持协议系列”)
E(EAFNOSUPPORT,“协议不支持的地址系列”)
E(EADDRNOTAVAIL,“地址不可用”)
E(网络故障,“网络故障”)
E(ENETUNREACH,“网络不可访问”)
E(网络重置,“网络连接重置”)
E(ECONABORTED,“连接中止”)
E(ENOBUFS,“没有可用的缓冲区空间”)
E(EISCON,“插座已连接”)
E(ENOTCONN,“未连接插座”)
E(ESHUTDOWN,“套接字关闭后无法发送”)
E(EALREADY,“操作已在进行”)
E(EINPROGRESS,“运行中”)
E(ESTALE,“过时文件句柄”)
E(EREMOTEIO,“远程I/O错误”)
E(EDQUOT,“超出配额”)
E(Enomidia,“未找到培养基”)
E(EMEDIUMTYPE,“错误的介质类型”)
E(0,“无错误信息”)
}
返回“”;
}
#未定义的

您对
strerror
的实现是正确的。但是您的C标准库中的标准版本可能是区域设置感知的(请参阅),这使得它不可重入

实际上,
errno
现在(通常)是一个宏,它被扩展为一些函数调用

在我的
/usr/include/x86_64-linux-gnu/bits/errno.h
内部头中有:

extern int *__errno_location (void) __THROW __attribute__ ((__const__));
#   define errno (*__errno_location ())

strerror\u r
的存在是为了从某个错误号中填充缓冲区(必须是特定于线程的)。

strerror不正是您想要的吗?他们忘记了
常量
,可能会覆盖缓冲区,但除此之外,它看起来还可以。@nwp手册页上说字符串“不能由应用程序修改,但可以由后续调用strerror()修改”。这使得标准的
strerror
不可重入,可重入性通过
strerror\u r
解决,这很笨拙,因为您必须猜测一个好的缓冲区大小。带有
const char*
字符串的简单开关没有任何这些问题。C标准的第7.5节要求
errno
是一个宏:
errno
扩展为可修改的左值,该左值具有类型
int
和线程本地存储持续时间,其值由多个库函数设置为正错误数。如果为了访问实际对象而抑制宏定义,或者程序使用名称定义标识符<