3

私のアプリケーションでは、ビットマップ イメージのスタックから読み取った「ボリューム データ」を格納するためにメモリを割り当てています。

データを「unsigned char」に保存し、割り当て中に、最初にデータ全体に連続メモリブロックを割り当てようとしました。それが失敗した場合は、分散割り当てを試みます(画像ごとに1つの小さなメモリブロック)。

unsigned char *data;

これがメモリを割り当てる私の方法です。「tryContinouseBlock = true」で呼び出します。

 bool RzVolume::initVolumeData(int xsize, int ysize, int zsize, int bbpsize,bool tryContinouseBlock) {
        this->nx = xsize;
        this->ny = ysize;
        this->nz = zsize;
        this->bbp_type=bbpsize;

        bool succ = false;

        if (tryContinouseBlock) {
            succ = helper_allocContinouseVolume(xsize, ysize, zsize, bbpsize);
        }

        if (!succ) {
            succ = helper_allocScatteredVolume(xsize, ysize, zsize, bbpsize);
        } else {
            isContinousAlloc = true;
        }
        if (!succ) {
            qErrnoWarning("Critical ERROR - Scattered allocation also failed!!!!");
        }
        return succ;

    }



    bool RzVolume::helper_allocContinouseVolume(int xsize, int ysize, int zsize,
            int bbpsize) {
        try {
            data = new unsigned char*[1];
            int total=xsize*ysize*zsize*bbpsize;
            data[0] = new unsigned char[total];
            qDebug("VoxelData allocated - Continouse! x=%d y=%d Z=%d bytes=%d",xsize,ysize,zsize,xsize * ysize * zsize * bbpsize);
        } catch (std::bad_alloc e) {
            return false;
        }

        return true;

    }

bool RzVolume::helper_allocScatteredVolume(int xsize, int ysize, int zsize,
        int bbpsize) {
    data = new unsigned char*[zsize];
    //isContinousAlloc=false;
    int allocCount = 0;
    try { //Now try to allocate for each image
        for (int i = 0; i < zsize; i++) {
            data[i] = new unsigned char[xsize * ysize];
            allocCount++;
        }
    } catch (std::bad_alloc ee) {
        //We failed to allocated either way.Failed!

        //deallocate any allocated memory;
        for (int i = 0; i < allocCount; i++) {
            delete data[i];
        }
        delete data;
        data = NULL;
        return false;
    }
    qDebug("VoxelData allocated - Scattered!");
    return true;
}

このコードを 32 ビットと 64 ビットの両方のプラットフォームで実行したいと考えています。

問題は、64 ビット環境 (12Gb メモリ) でも、(1896*1816*1253) サイズのデータ​​ (bbpsize=1) をロードするとhelper_allocContinouseVolume()メソッドが失敗することです。そのため、メモリアドレスアクセスに「int」データ型を使用し、「int」の最大値は4294967295です。

32 ビット環境と 64 ビット環境の両方で、次のコードは値 "19282112" を与えます。

 int sx=1896;
 int sy=1816;
 int sz=1253;
 printf("%d",sx*sy*sz);

正しい値は「4314249408」です。

では、これにはどのデータ型を使用すればよいでしょうか? 32bit 環境と 64bit 環境で同じコードを使いたい。

4

3 に答える 3

2

32GB を超えるメモリと大規模なデータセットを備えたワークステーションで作業しているときに、同じ問題が頻繁に発生します。

size_t一般に、このような状況ですべてのインデックスに使用する適切なデータ型は、「通常」ポインターのサイズと一致しmemcpy()、他のライブラリ関数との互換性を維持するためです。

唯一の問題は、32 ビットでは、オーバーフローのケースを検出するのが難しい場合があることです。そのため、最大整数サイズを使用して別のメモリ計算ステージを使用して、32 ビットでも可能かどうかを確認して、適切に処理できるようにすることをお勧めします。

于 2011-09-28T06:27:25.100 に答える
1

size_t最大の有効なオブジェクトサイズを記述するのに十分な大きさであると定義されています。したがって、一般的に、オブジェクトを割り当てるときは、それが使用するのに適切なサイズです。

ptrdiff_t任意の2つのアドレスの違いを記述できるように定義されています。

目的に合ったものを使用してください。そうすれば、適切なサイズであることが保証されます。

于 2011-09-28T07:10:24.703 に答える
1

から使用ptrdiff_t<stddef.h>ます。

理由: 署名されているため、unsigned が関係する暗黙的なプロモーションの問題を回避でき、16 ビットを除くすべてのシステムで必要な範囲を持ちます (形式的には 16 ビットでもうまく機能しますが、形式的には少なくとも 17 ( sic ) ビットのばかげた要件)。

于 2011-09-28T06:55:11.940 に答える