【问题标题】:Why is the buffer size in inet_ntoa 18?为什么 inet_ntoa 中的缓冲区大小为 18?
【发布时间】:2020-02-25 08:56:49
【问题描述】:

我查看了inet_ntoa 的实现,例如thisthis

我想知道为什么他们都分配一个 18 个字符的缓冲区。

如果我采用最大长度的 IPv4 地址字符串:255.255.255.255,我需要的大小是:每个八位字节为 3,点为 3,空终止符为 1。 3*4+3+1 = 16。

那么为什么我们需要这两个额外的字符呢?

第一个链接中的inet_ntoa 实现:

static __thread char buffer[18];

char *
inet_ntoa (struct in_addr in)
{
  unsigned char *bytes = (unsigned char *) ∈
  __snprintf (buffer, sizeof (buffer), "%d.%d.%d.%d",
              bytes[0], bytes[1], bytes[2], bytes[3]);
  return buffer;
}

【问题讨论】:

  • 因为inet_ntoa 正常工作所需的最大字节数是 16 个字节。这 2 个额外的字节未被使用,从未用于任何事情。
  • 那么为什么要声明额外的 2 个字节呢?
  • @LeeDanielCrocker 代码不是他写的。 OP 链接到实现 inet_ntoa 函数的 C 标准库的两个主要实现 - glibc 和仿生。我看到newlib 也有 18 个。而musl 有 16 个! freebsd 有 18 个。我想我猜是很久以前有人写了 18,其他人抄了。
  • @Yanbir 作者也没有,但他们从原始错误的作者那里得到了货物。只有 musl 的作者才能算数。
  • @AdrianMole 如果“基础”问题是根本原因,那么它至少应该是 20。这 18 允许四个组件中的两个多一个字符,在任何基础上都没有意义.

标签: c networking


【解决方案1】:

如果我取最大长度的 IPv4 地址字符串:255.255.255.255 我需要的大小是:每个八位字节 3 个,点 3 个,空值 1 个 终结者。 3*4+3+1 = 16。

那么为什么我们需要这两个额外的字符呢?

你的计算是正确的。存储inet_ntoa() 产生的点分十进制地址字符串只需要16 个字节,包括它的终止符。相关文档和规范至少早在 POSIX.1 2004 就指定了当前格式,据我所知,从未发布过任何其他格式的实现,因此我们只能推测为什么某些实现提供额外的空间。可能性包括但不一定限于

  • 错字或计算错误;
  • 缓冲区曾经(可能仍然是)用于不止一件事,而其他用途需要更多字节;
  • 一些实现用来格式化结果的算法得益于有几个额外的字节可以使用;
  • 为 slop 空间提供了额外的字节,以减轻假设性错误的影响。

今天在许多实现中观察到相同的额外字节可能支持多用途缓冲区替代方案,但这种观察也与对出现在某些早期实现中的那些字节的任何解释一致,可能是 BSD,并从那里传播到许多后续的。我倾向于后一种解释。

【讨论】:

  • 郑重声明,inet_ntoa() 最早出现在 BSD 4.3 中。
猜你喜欢
  • 1970-01-01
  • 2012-08-24
  • 1970-01-01
  • 2016-09-21
  • 1970-01-01
  • 1970-01-01
  • 2018-07-13
  • 2012-08-10
  • 1970-01-01
相关资源
最近更新 更多