有没有办法errno在编译时获得与编码时相关的任何字符串的最大大小(在预处理器时间会更好)?例如上限strlen(strerror(errno))?
我能想到的最好的是运行一个程序,在每个语言环境中对int范围进行强力搜索,以获取与每个{errno,locale}对关联的字符串,获取其大小,并生成标题在该系统上,然后将其挂钩到例如makefile或autoconf或其他任何东西.我想不出更好的方法,但它似乎是荒谬的:系统的标准库具有内置的信息,如果只是隐含的话.获取这些信息真的没有好办法吗?
好的,我承认C和/或C++标准可能允许在运行时生成的错误字符串,例如特定情况消息(例如,strerror(EINVAL)给出从errno最后一次设置时的其他运行时元数据集导出的字符串,或者其他东西) -不知道这是允许的,其实我欢迎这样的实现,但我从来没有听说过一个现有的这这样做,或者有一个给定{不止一个字符串errno,区域设置}对.
对于上下文,我特别想要的(但我认为这个问题在更广泛的方式中是有价值的,正如评论中讨论的那样)导致这个问题是能够使用与errnosyscall/function中相关联的错误字符串writev.在我的特定用例中,我使用的是字符串argv 和链接 errno字符串.这将我的"最坏情况"长度设置为ARG_MAX+ some max errno string length+ size of a few other small strings).
我咨询过的每个*nix文档似乎都表示writev将(或"可能",这个差异在这种情况下产生的好处)错误输出,如果值的总和溢出则errno设置为.直觉上,我知道我看到的每一根弦都很短,实际上这不是问题.但我不希望我的代码在某些系统上神秘地无法打印错误,如果这个假设可能是假的.所以我编写了代码来处理这种情况 - 但与此同时,我不希望为通常显然不需要它的平台编译额外的代码.EINVALiov_lenSSIZE_MAXerrno
到目前为止,答案和评论的综合输入使我倾向于认为在我的特定用例中,"正确"的解决方案是截断长时间的错误消息 - 但这就是为什么我问我最初的做法:这样的信息也有助于选择缓冲区的大小为strerror_r/ strerror_s(*nix/Windows),甚至是否定答案(例如"你不能真正做到这一点")在我看来对其他人的教育有用.
这个问题包含strerror_r了VxWorks上给出的字符串的答案,但我不觉得将其推广到所有系统.
Car*_*ell 15
您构建的C库可能不一样(可能使用ABI兼容的C库),甚至是您运行的C库的完全版本(在GNU/Linux上考虑glibc 2.2.5与glibc 2.23),因此计算返回的与语言环境相关的字符串的最大大小strerror只能在进程执行期间在运行时完成.除此之外,可以在任何时间在目标系统上更新区域设置转换,并且这再次使该上限的任何预先计算无效.
遗憾的是,无法保证返回的值strerror在进程的生命周期内是恒定的,因此它们也可能在以后更改,从而使绑定的任何早期计算无效.
我建议使用strerror_r来保存错误字符串,并避免任何可能调用sterror的非多线程感知库的问题,并可能在复制时更改字符串的结果.然后,不是在运行中翻译字符串,而是使用保存的结果,并可能截断为SSIZE_MAX(实际上永远不会发生).
我不知道C或C++标准对这些消息的长度做出任何断言.但是,您感兴趣的平台可能会提供一些更强大的实现定义保证.
例如,对于POSIX系统,我发现了以下内容limits.h.
应在以下所有实现中定义以下常量
<limits.h>:
- [...]
{NL_TEXTMAX}
消息字符串中的最大字节数.
最低可接受价值:{_POSIX2_LINE_MAX}
我认为strerror由此产生的错误消息将属于此类别.
也就是说,我无法在我的系统上获得此宏.但是,我确实有_POSIX2_LINE_MAX(从<unistd.h>).它是#defined到2048.由于标准只说这是一个下限,但这可能不是太有用.