分配大量内存并使用 size_t?
在我的应用程序中,我分配内存来存储从位图图像堆栈读取的“体积数据”。
我将数据存储在“无符号字符”中,并且在分配期间,首先我尝试为整个数据分配连续的内存块。如果失败,则尝试分散分配。(每个图像一个小内存块)。
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”。
那么我应该使用哪种数据类型呢?我想在 32 位和 64 位环境中使用相同的代码。
In my application ,I am allocating memory to store "volume data" which read from stack of bitmap images.
I stored the data in a "unsigned char" and ,during allocation, first I try to allocate continuous memory-block for entire data.if that fails then tries for scattered allocation.(one small memory-block for each image).
unsigned char *data;
here is my method to allocate memory,I call with "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;
}
I want this code to run in both 32bit and 64bit platforms.
Now the problem is, even in 64Bit environment (with 12Gb memory) ,helper_allocContinouseVolume() method fails when I load (1896*1816*1253) size of data (with bbpsize=1).
Its because of, I use "int" datatype for memory address access and the maxmum of "int" is 4294967295.
In both 32bit and 64bit environment following code gives the value "19282112".
int sx=1896;
int sy=1816;
int sz=1253;
printf("%d",sx*sy*sz);
where the correct value should be "4314249408".
So which datatype should I use for this ? I want to use the same code in 32bit and 64bit environments.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
在使用 > 的工作站上工作时,我经常遇到同样的问题。 32GB 内存和大型数据集。
size_t
通常是在这种情况下用于所有索引的正确数据类型,因为它“通常”匹配指针大小并与memcpy()
和其他库函数保持兼容。唯一的问题是,在 32 位上,可能很难检测到溢出的情况。因此,可能值得使用最大整数大小的单独内存计算阶段,看看它是否可以在 32 位上实现,以便您可以优雅地处理它。
I encounter the same problem very often when working on workstations with > 32GB of memory and large datasets.
size_t
is generally the right datatype to use for all indices in such situations as it "usually" matches the pointer size and stays compatible withmemcpy()
and other library functions.The only problem is that on 32-bit, it may be hard to detect cases where it overflows. So it may be worthwhile to use a separate memory computation stage using the maximum integer size to see if it's even possible on 32-bit so that you can handle it gracefully.
size_t
被定义为足够大以描述最大的有效对象大小。因此,一般来说,在分配对象时,使用的大小才是正确的。ptrdiff_t
被定义为能够描述任意两个地址之间的差异。使用适合您目的的那个。这样您就可以确保它具有合适的尺寸。
size_t
is defined to be large enough to describe the largest valid object size. So generally, when allocating objects, that is the right size to use.ptrdiff_t
is defined to be able to describe the difference between any two addresses.Use the one that fits your purpose. That way you'll be ensured it has the appropriate size.
使用
中的ptrdiff_t
。原因:它是有符号的,从而避免了涉及无符号的隐式提升的问题,并且它在除 16 位之外的任何系统上都有必要的范围(在形式中它也可以在 16 位上很好地工作,但那是因为形式具有至少 17 (sic) 位的愚蠢要求)。
Use
ptrdiff_t
from<stddef.h>
.Reason: it's signed, thus avoiding the problems with implicit promotion where unsigned is involved, and it has the requisite range on any system except 16-bit (in the formal it works nicely also on 16-bit, but that's because the formal has the silly requirement of at least 17 (sic) bits).