1

私はかなり前にオブジェクト プーリング システムを作成しました (そのほとんどは、当時必要だった部分だけです)。プログラムが進化した今、プールを実装したときにはなかったと思われる欠陥を発見しました。

基本的に、プールはオブジェクトをコンストラクターとして受け取り、それをリフレクションで複製して、そのオブジェクトの配列を作成します。プールにオブジェクトを作成する関数の実装は次のとおりです。

        poolSize i = 0;
        T[] oldData = null;

        if (this.chunks != null && this.chunks.Length > 0)
        {
            oldData = new T[this.depth];
            Array.Copy(this.chunks, oldData, this.chunks.Length);
        }

        this.chunks = new T[this.depth + this.depthIncrement];

        if (oldData != null)
        {
            Array.Copy(oldData, this.chunks, oldData.Length);
        }

        for (i = this.depth; i < this.depth + this.depthIncrement; i++)
        {

            this.chunks[i] = Cloner.CloneObjectWithIL(this._template);
            this.freeQueue.Add(i);
        }

        this.depth += this.depthIncrement;

ここで、Object.ReferenceEquals(pool.chunks[0], pool.chunks[1]) をチェックすると false が返されます。したがって、配列の各インデックスは、1 つのオブジェクトへの単なる参照の集まりではなく、独自のオブジェクトであるように見えます。

メイン コードでは、GetObject メソッドを使用して、プールからオブジェクトをフェッチします。

    public T GetObject(T tmp)
    {
        T retObj = tmp;

        this.chunks[this.volume] = retObj;
        this.usedQueue.Add(this.volume);
        this.volume++;

        return retObj;
    }

保護されたメモリ エラー (C# で SEGFAULT に相当するエラー) が発生していたので、デバッグを続けました。したがって、プールの背後にある目的の一部を無効にするため、通常は使用しないコードを使用します。

Map.Entity tmp = Map.Entity.EntityPool.chunks[0];
tmp.SetPosition(m, 1, 9);

その後、ブレークポイントを追加してチャンク配列を見ると、チャンク配列のすべての要素の位置は (1, 9) ですが、インデックス 0 を除いてすべて (0, 0) である必要があります。

ここで何が欠けていますか?

4

0 に答える 0