3

私は pg_size_pretty() で遊んでいましたが、大きな値を渡すと負の値を返し始めることがわかりました。これは私のテストです:

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

理由を説明していただけますか?ありがとう。

4

2 に答える 2

5

最高の符号付き 64 ビット整数は 922337203685477587 です。これは、問題の数値よりもわずかに大きいだけです。確かに のどこかにオーバーフローがありpg_size_prettyます。

コメントに記載されているコードに基づいてpg_size_pretty、数値を丸めようとしており、最大符号付き 64 ビット int より大きい中間値を使用してそうしています。9223372000000000000 + 1024*1024*1024*1024/2 = 9223372549755813888 となり、922337203685477587 よりも大きくなります。

更新: 2 番目の段落を追加し、オーバーフローが呼び出し元にないことを明確にしました。

于 2011-04-24T01:42:51.670 に答える
5

あなたは溢れているのではなく、pg_size_pretty溢れています。pg_size_pretty関数は次の値をとるはずbigintです:

pg_size_pretty(bigint)
text
バイト単位のサイズを、サイズ単位を持つ人間が読める形式に変換します

そして、完全に有効であり、9223372000000000000 < 9223372036854775808それで正しいことを行う必要があります. バグを PostgreSQL の担当者に報告して、賞賛を得る必要があります。9223372000000000000bigintpg_size_pretty

更新: 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範囲内に戻すことができます。

于 2011-04-24T02:02:54.043 に答える