gonypage diary

トップ > 2021/10

2021/10/17

18:39 .NETのbyte[]で確保できる領域は2GB弱まで

Qtベースの医療画像処理アプリケーションを開発しているが、Looking GlassなどのUnity SDKを使用する立体視デバイスに対応するためにUnityベースのコンパニオンアプリケーションを用意し、そちらにネットワーク経由でデータを送信することで連携を実現しようとしている。

すでに基本的な動作はできているのだが、3000枚程度のCTデータを送信すると正しく動作しないことがわかり、問題を調査したところデータサイズが2GBを超える場合にUnity側で受信用のバッファの確保に失敗しているらしいということがわかってきた。

調べてみると.NETのドキュメントにbyteとサイズが1バイトの構造体のArrayのサイズは2147483591(0x7FFFFFC7)まで、それ以外はArrayのサイズは2146435071(0x7FEFFFFF)まで、という記述を見つけた。だとするとbyte[]を使用して2GB超のバッファを確保することはできないということになる。それは困る。

困るので確認のために以下のテストコードを書いた:

using System;

namespace TestByteArray
{
    class Program
    {
        public static void Main(string[] args)
        {
            TestAllocation(0x7FEFFFFFl);
            TestAllocation(0x7FF00000l);
            TestAllocation(0x7FFF0000l);
            TestAllocation(0x7FFFF000l);
            TestAllocation(0x7FFFFF00l);
            TestAllocation(0x7FFFFFC7l);
            TestAllocation(0x7FFFFFC8l);
            TestAllocation(0x7FFFFFF0l);
            TestAllocation(0x7FFFFFFFl);
            TestAllocation(0x80000000l);
        }

        private static void TestAllocation(long size)
        {
            Console.Write("Trying to allocate {0}(0x{0:X}) bytes...\n", size);
            try
            {
                var buffer = new byte[size];
                Console.Write("Succeeded.\n");
            }
            catch (Exception e)
            {
                Console.Write("Failed. Thrown exception:\n");
                Console.Write("{0}\n", e.ToString());
            }
            Console.Write("\n");
        }
    }
}

出力結果は以下の通り:

Trying to allocate 2146435071(0x7FEFFFFF) bytes...
Succeeded.

Trying to allocate 2146435072(0x7FF00000) bytes...
Succeeded.

Trying to allocate 2147418112(0x7FFF0000) bytes...
Succeeded.

Trying to allocate 2147479552(0x7FFFF000) bytes...
Succeeded.

Trying to allocate 2147483392(0x7FFFFF00) bytes...
Succeeded.

Trying to allocate 2147483591(0x7FFFFFC7) bytes...
Succeeded.

Trying to allocate 2147483592(0x7FFFFFC8) bytes...
Failed. Thrown exception:
System.OutOfMemoryException: Exception of type 'System.OutOfMemoryException' was thrown.
   at TestByteArray.Program.TestAllocation(Int64 size) in C:\Users\gony\Documents\TestByteArray\TestByteArray\Program.cs:line 31

Trying to allocate 2147483632(0x7FFFFFF0) bytes...
Failed. Thrown exception:
System.OutOfMemoryException: Exception of type 'System.OutOfMemoryException' was thrown.
   at TestByteArray.Program.TestAllocation(Int64 size) in C:\Users\gony\Documents\TestByteArray\TestByteArray\Program.cs:line 31

Trying to allocate 2147483647(0x7FFFFFFF) bytes...
Failed. Thrown exception:
System.OutOfMemoryException: Exception of type 'System.OutOfMemoryException' was thrown.
   at TestByteArray.Program.TestAllocation(Int64 size) in C:\Users\gony\Documents\TestByteArray\TestByteArray\Program.cs:line 31

Trying to allocate 2147483648(0x80000000) bytes...
Failed. Thrown exception:
System.OverflowException: Array dimensions exceeded supported range.
   at TestByteArray.Program.TestAllocation(Int64 size) in C:\Users\gony\Documents\TestByteArray\TestByteArray\Program.cs:line 31

ドキュメントの通り0x7FFFFFC7バイトまでは確保できていることがわかる。それ以上確保しようとすると例外を投げられるわけだが、0x80000000バイト確保しようとすると飛んでくる例外がOverflowExceptionに変わるところも気になる。これはもしかして確保サイズが暗黙的に符号付き32ビットに変換されていて、負のサイズで確保しようとしているのでは...

扱いたいデータのサイズが2GBを超えるなんてうちの業界ではザラなので大変困る制約である。もう64ビットデータなんてさらっと扱えて当たり前の時代だと思っていたので、こんな制約にハマるとは思ってはいなかった。今はちょっと対策を考えたくないので後回しにする...

2021/10/31

19:21 Monthly Update

月末の日記ですが皆さんいかがお過ごしでしょうか。今月は更新したが全然日記ではないことには変わりはない。

仕事はなんか政治だったり虚無僧だったり。しばらくこんな感じだろうか...

プライベート。そんなに遊びに行けたりしているわけではないんだが、週末に横浜市内くらいなら電車なり車なりでそこそこ遊びに行っていた。あっ町田の満洲行ったから東京にも行ってたね! 町田たぶん初めて行ったが大都会だった。

ぎょうざの満洲 町田パリオ店でおひる。紹興酒の熱燗を頼むとランちゃんデザインの徳利で出てくることを学んだ pic.twitter.com/Nm9IceTeKO

— gony(KMS) (@gony) October 24, 2021

といったところで憎きCOVID-19についても。飲食店等での営業制限はなくなったが今の所リバウンドはないようだ。ただ、実効再生産数は上昇してきていて減少についてはそろそろ限界かなあという雰囲気に見える。今後どうなるかはさっぱりわからないがまあ走りながらやっていくしかないんだろう。

そんなこんなで、充分に健康に気をつけながら実り多い生活を営んでいきましょう。

では、例によってラーメンで情報量水増しのコーナーです:

横浜橋商店街を散策中、路地に錢爺という台湾料理屋さんを発見したので吸い込まれて牛肉麵でおひる。メニューもいろいろあるのでまた来る必要がある pic.twitter.com/j12zA50uE2

— gony(KMS) (@gony) October 2, 2021

一品香でおひる。担々たんめんって前からあったっけ... pic.twitter.com/vXScfXGPVM

— gony(KMS) (@gony) October 4, 2021

備蓄消費でおひる。神田のお店も行きたいねえ pic.twitter.com/f0n8FLH9uy

— gony(KMS) (@gony) October 7, 2021

川崎式のニュータンタンメンはこの辺だと色々なところで食べられるが、発祥の元祖ニュータンタンメン本舗では食べたことがなかったので初訪問。めちゃ辛だと結構辛い。ニンニクは大きめに刻まれていて存在感がすごい。おいしかった pic.twitter.com/p3zaVdyXu9

— gony(KMS) (@gony) October 9, 2021

北里家でおひる。悲しいことがあった日は美味しいものを食べましょう pic.twitter.com/KfmF26H8wf

— gony(KMS) (@gony) October 14, 2021

幸楽苑の酸辣湯麺激辛でおひる。ちょろい激辛オタクなので商品名に激辛と付くとついオーダーしてしまう脆弱性があるが、それはさておきおいしかった pic.twitter.com/dFabbsY36v

— gony(KMS) (@gony) October 17, 2021

中華料理福濱でおひる。通勤路のしばらく開店準備していた店が開いたようなので。お手頃で本格感あってよいのでは pic.twitter.com/rlS3iFIofI

— gony(KMS) (@gony) October 25, 2021

幕張メッセフードコートのラーメンでおひる。よくある業務用スープの醤油ラーメンかと思ったらとんこつだったが、ロイヤル運営らしくて納得 pic.twitter.com/Rh9bISgg1u

— gony(KMS) (@gony) October 27, 2021

啜磨専科でおひる pic.twitter.com/YfVwVmLsF2

— gony(KMS) (@gony) October 31, 2021

結構食べたねえ...

Generated by Rui 0.4.1