为什么 pg_size_pretty 返回负值?

发布于 2024-11-02 19:03:46 字数 293 浏览 5 评论 0原文

我正在使用 pg_size_pretty() ,我发现当我传递一个很大的值时,它开始返回负值。 这是我的测试:

select pg_size_pretty(9223370000000000000); -- "8388606 TB"
select pg_size_pretty(9223371000000000000); -- "8388607 TB"
select pg_size_pretty(9223372000000000000); -- "-8388607 TB"

你能解释一下为什么吗? 谢谢。

I was playing with pg_size_pretty() and I've discovered that when I pass it a great value it starts to return negative value.
This is my test:

select pg_size_pretty(9223370000000000000); -- "8388606 TB"
select pg_size_pretty(9223371000000000000); -- "8388607 TB"
select pg_size_pretty(9223372000000000000); -- "-8388607 TB"

Can you explain me why?
Thanks.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

挽袖吟 2024-11-09 19:03:46

最高的有符号 64 位 int 是 922337203685477587。这仅比所讨论的数字多一点点。肯定是 pg_size_pretty 中的某个地方存在溢出。

根据评论中提到的代码,pg_size_pretty 正在尝试对数字进行舍入,并使用大于最大有符号 64 位 int 的中间值来实现此目的。 9223372000000000000 + 1024*1024*1024*1024/2 = 9223372549755813888,大于 922337203685477587。

更新:添加了第二段并澄清溢出不在调用方中。

The highest signed 64 bit int is 922337203685477587. That's but a tiny bit more than the number in question. Surely there's an overflow somewhere in pg_size_pretty.

Based on the code mentioned in a comment, pg_size_pretty is attempting to round the number and does so using an intermediary value that's larger than the max signed 64-bit int. 9223372000000000000 + 1024*1024*1024*1024/2 = 9223372549755813888, which is larger than 922337203685477587.

Update: Added second paragraph and clarified that the overflow isn't in the caller.

倾听心声的旋律 2024-11-09 19:03:46

你没有溢出,pg_size_pretty正在溢出。 pg_size_pretty 函数应该采用 bigint

pg_size_pretty(bigint)
文本
将字节大小转换为具有大小单位的人类可读格式

并且 9223372000000000000 9223372000000000000 9223372036854775808 所以 9223372000000000000 是一个完全有效的 bigint 并且 pg_size_pretty 应该用它做正确的事情。您应该向 PostgreSQL 人员报告错误并赢得荣誉。

更新:检查 PostgreSQL 源代码(感谢 Jeremiah Peschka 提供链接)向我们展示了错误所在:

491                 else
492                 {
493                     mult *= 1024;
494                     snprintf(buf, sizeof(buf), INT64_FORMAT " TB",
495                              (size + mult / 2) / mult); /* OVERFLOW! */
496                 }

如果 size 接近 int64 的限制,然后向其添加 mult/2 将会溢出,然后再除以 mult 使其回到范围内。

You are not overflowing, pg_size_pretty is overflowing. The pg_size_pretty function is supposed to take a bigint:

pg_size_pretty(bigint)
text
Converts a size in bytes into a human-readable format with size units

And 9223372000000000000 < 9223372036854775808 so 9223372000000000000 is a perfectly valid bigint and pg_size_pretty should do The Right Thing with it. You should report a bug to the PostgreSQL people and win kudos.

UPDATE: Examining the PostgreSQL source code (thanks to Jeremiah Peschka for providing the link) shows us where the bug is:

491                 else
492                 {
493                     mult *= 1024;
494                     snprintf(buf, sizeof(buf), INT64_FORMAT " TB",
495                              (size + mult / 2) / mult); /* OVERFLOW! */
496                 }

If size is close to the limit of int64, then adding mult/2 to it will overflow before the following division by mult can bring it back into range.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文