什么是GNU / Linux上的WONTFIX错误,以及如何解决它们?

Linux和GNU用户空间(glibc)似乎都有一些“WONTFIX”错误,即负责方声称他们不愿修复的错误,尽pipe明显违反了ISO C和/或POSIX的要求,但我并不知情任何资源的程序员列出这些错误和build议周围的工作。

这里有几个想到:

  • Linux UDP select错误: select (和相关接口)在收到数据包后立即标记一个UDP套接字文件描述符,但不确认校验和。 在后续的recv / read / etc中,如果校验和无效,呼叫将被阻塞。 解决此问题需要始终将UDP套接字设置为非阻塞模式并处理EWOULDBLOCK条件。 如果我没有记错的话,MaraDNS是第一个受此bug影响的着名项目,也是第一个投诉(不成功)修复的项目。 注意:正如Martin诉Löwis所指出的,显然这个bug已经被修复了。 如果您需要支持真正过时的Linux版本,则可能只需要解决方法。
  • GNU C库中的printf系列在指定字段精度(如%.3s )时将%s参数错误地视为多字节string而不是字节string,可能导致截断输出。 我知道除了replace整个printf子系统(或者简单地不使用带有非多字节字符string的printf系列函数)之外,没有任何解决方法,但是如果要在UTF中使用snprintf来处理遗留代码页string,这可能会有问题-8区域设置)。
  • 某些系统调用错误的errno结果代码(不记得哪些是正确的)。 通常这些很容易检查你是否只是阅读GNU / Linux的手册页并将它们与标准进行比较。 (我找不到这个参考资料,也许我错了。最接近的是我能find的是ENOTSUPEOPNOTSUP具有相同的值的问题;参见PDTR 24715 。

有什么更多的错误和解决办法,我们可以添加到这个列表? 我提出这个问题的目标是:

  1. 要build立一个更完整的错误列表,以便新手和有经验的程序员能够快速地意识到在GNU / Linux上运行一个预期的可移植程序时可能出现的潜在问题。
  2. 为了利用SO集体大脑为尽可能多的这样的错误想出聪明而不引人注目的标准解决方法,而不是每个人在被蜇伤后都不得不发明自己的解决方法,并且可能以次优,丑陋或者恶意的方式来做 – 或者更糟然而,以打破对更加一致的系统的支持的方式。

我无法重现您声明的printf问题。 运行程序

 #include <stdio.h> #include <locale.h> int main() { setlocale(LC_ALL, ""); printf("%.4s\n", "Löwis"); return 0; } 

在de_DE.UTF-8语言环境中打印“Löw”,这对我来说很正确:我询问了4个字节,并获得了4个字节(ö是2个字节)。 如果图书馆计算多字节字符,输出应该是“Löwi”。 这是glibc 2.11.2。

编辑 :改变字符串为“%.2s \ n”只会打印“L”,即只有一个字节。 但是,这符合规范 ,这就是说

如果指定了精度,则不应超过这么多字节。

(重点是我的),然后

任何情况下都不能写出部分字符。

因此,由于打印两个字节(即L和ö的首字节)会导致部分字符被写入,所以打印不完整的UTF-8将不合格。

我不相信UDP问题确实存在。 在当前的Linux内核中,udp_poll读取

 /** * udp_poll - wait for a UDP event. * @file - file struct * @sock - socket * @wait - poll table * * This is same as datagram poll, except for the special case of * blocking sockets. If application is using a blocking fd * and a packet with checksum error is in the queue; * then it could get return from select indicating data available * but then block when reading it. Add special case code * to work around these arguably broken applications. */ unsigned int udp_poll(struct file *file, struct socket *sock, poll_table *wait) { unsigned int mask = datagram_poll(file, sock, wait); struct sock *sk = sock->sk; /* Check for false positives due to checksum errors */ if ((mask & POLLRDNORM) && !(file->f_flags & O_NONBLOCK) && !(sk->sk_shutdown & RCV_SHUTDOWN) && !first_packet_length(sk)) mask &= ~(POLLIN | POLLRDNORM); return mask; } 

所以在我看来,它确实隐藏了具有错误校验和的UDP数据包,不能通过选择/轮询来报告。 自版本85584672(2009)开始使用此版本的代码。 但是甚至在(至少从2005年起)之前,代码显然已经在select / poll中做了同样的丢弃坏包。