【发布时间】:2018-11-16 07:41:54
【问题描述】:
问题
有没有办法在编译时获得与errno 相关的任何字符串的最大大小(在预处理器时会更好)?例如。 strlen(strerror(errno)) 的上限?
我的想法
我能想到的最好的方法是运行一个程序,在 int 的范围内,在每个语言环境上进行暴力搜索,以获取与每个 {errno, locale} 对关联的字符串,获取它的大小,然后在该系统上生成一个标头,然后将其挂接到例如一个makefile或autoconf或其他什么。我想不出更好的方法来做到这一点,但这样做似乎很荒谬:系统的标准库具有内置的信息,即使只是隐式的。真的没有很好的方法来获取这些信息吗?
好的,我承认 C 和/或 C++ 标准可能允许在运行时生成错误字符串,例如特定情况的消息(例如,strerror(EINVAL) 给出了一个从上次设置 errno 时设置的其他运行时元数据派生的字符串,或者其他什么) - 不确定是否允许 ,我会实际上欢迎这样的实现,但我从来没有听说过这样的实现,或者对于给定的 {errno, locale} 对有多个字符串。
动机
对于上下文,我特别想要的是能够使用与 errno 关联的错误字符串(但我认为这个问题在更普遍的方式中很有价值,正如 cmets 中所讨论的那样)导致这个问题在系统调用/函数writev 中。在我的特定用例中,我使用了argv 和 errno-linked 字符串中的字符串。这将我的“最坏情况”长度设置为ARG_MAX + some max errno string length + size of a few other small strings)。
我查阅过的每个 *nix 文档似乎都表明 writev 将(或“可能”,在这种情况下这种差异产生的一点好处)错误,如果将 errno 设置为 EINVAL iov_len 值溢出 SSIZE_MAX。直觉上,我知道我见过的每个errno 字符串都很短,实际上这不是问题。但是如果这个假设可能是错误的,我不希望我的代码在某些系统上神秘地无法打印错误。所以我编写了代码来处理这种情况 - 但同时,我不希望为通常显然不需要它的平台编译额外的代码。
到目前为止,答案和 cmets 的组合输入使我倾向于认为在我的特定用例中,“正确”的解决方案是截断非常长的消息 - 但这就是为什么我问这个问题我是如何最初是这样做的:这些信息还有助于为strerror_r/strerror_s(分别为*nix/Windows)选择一个缓冲区的大小,甚至一个否定的答案(例如“你不能真的这样做”)在我的认为对他人的教育有用。
相关
This question 包含对 VxWorks 上strerror_r 给出的字符串的答案,但我不方便将其推广到所有系统。
【问题讨论】:
-
C 和 C++ 是不同的语言!
-
@Olaf 虽然我总体上感谢您为明确这一区别所做的努力,但我相信在这种情况下,将 C 和 C++ 放在一起是合法的,因为它们都使用了
errno概念.选择其中一个标签而不是另一个标签是任意的。 -
您可以选择自己的最大值,并在运行时剪辑错误消息吗?
-
我可能遗漏了一些东西,但是在 ssize_t 大于 int8_t 的任何平台上,大于 ssize_t 的错误消息似乎完全是疯狂的。
-
C(我怀疑是 C++)标准对
SSIZE_MAX没有帮助,因为它没有定义SSIZE_MAX。如果SSIZE_MAX对您的代码很重要,建议标记定义它的感兴趣的环境。