【发布时间】:2014-09-22 14:26:49
【问题描述】:
在开始之前,是的,我已经阅读了a possible duplicate、malloc being weird in linux、cplusplus.com on malloc 并在 google 上进行了一些搜索。
我有一个需要非常大的二维数组的科学计算问题。我正在关注“C 中的数字食谱”副本中的代码,并且在我的二维数组中间遇到了未分配内存的问题。我在 Windows 中工作,并且在 MSVC 2012 中使用 c++。
这是我的二维数组分配
unsigned long nrl=0;
unsigned long nrh=749774;
unsigned long ncl=0
unsigned long nch=250657;
unsigned long i, nrow=nrh-nrl+1,ncol=nch-ncl+1;
double **m;
if((size_t)(nrow*ncol)<(size_t)nrow){
m=NULL;
return m;
}
/*allocate pointers to rows*/
m=(double **)malloc((size_t)(nrow)*sizeof(double*));
if (!m){
m=NULL;
return m;
}
/*allocate rows and set pointers to them*/
m[nrl]=(double *) malloc((size_t)((nrow*ncol)*sizeof(double)));
if(!m[nrl]){
free(m[nrl]);
free(m);
m=NULL;
return m;
}
for(i=nrl+1;i<=nrh;i++)m[i]=m[i-1]+ncol;
/*The 2D array should now be callable as m[nrow][ncol]*/
/*Pseudo-code below*/
m[0][0] == Good, allocated memory
m[125][200923] == Unallocated, crashes program
m[nrh-1][nch-1] == Good, allocated memory
如果内存分配失败,我目前依靠 malloc 返回 NULL(如果我尝试分配非常非常大的数组,我实际上会得到 NULL 值。
另外,我尝试了double *m = new double[nch*nrh],但这给了我一个内存分配错误。我愿意接受有关替代实现的任何建议,但我需要能够知道分配是否有效并在必要时重新分配较小的块。
编辑:
这是一个 c 函数,但我的大部分代码都是用 c++ 编写的。
更新:
感谢大卫,我能够解决这个问题。从
更改我的溢出检查if((size_t)(nrow*ncol)<(size_t)nrow)
到
if(SIZE_MAX/nrow < ncol || SIZE_MAX/ncol < nrow || nrow*ncol<nrow)
允许 malloc 在它应该失败时失败。
【问题讨论】:
-
好吧,您正在尝试分配 1.36 TB 的数据,所以是的,这会给您带来内存分配错误。
-
((size_t)nrow)*((size_t)ncol)比(size_t)(nrow*ncol)更有意义。 -
我认为不需要投射。他们最终是
int。如果数组很大,你应该注意溢出问题。如果它很大,我认为你也不需要考虑连续分配,因为你希望它只有在所有数据都适合缓存时才是连续的。 -
很遗憾您使用的是 MSVC,因为它们不符合标准。使用真正的现代 C 编译器,您将拥有真正的 2D 动态矩阵,而您不必使用您正在使用的这些假矩阵。在 C99 中,这只是
double (*m)[ncol] = malloc(sizeof(double[nrow][ncol]));。没有多重分配,没有显式大小计算,......也不要使用 C++ 编译器来编译 C。这是两种不同的语言。 -
@JensGustedt 导致这种情况的不是 MSVC 的选择,而是代码来自 NR 并且完全古老的事实。
标签: c arrays memory-management