pfc*_*pfc 13 c c++ memory malloc
我正在使用128GB内存的服务器来进行一些计算.我需要malloc()一个大小为56120*56120的2D float数组.示例代码如下:
int main(int argc, char const *argv[])
{
float *ls;
int num = 56120,i,j;
ls = (float *)malloc((num * num)*sizeof(float));
if(ls == NULL){
cout << "malloc failed !!!" << endl;
while(1);
}
cout << "malloc succeeded ~~~" << endl;
return 0;
}
Run Code Online (Sandbox Code Playgroud)
代码编译成功,但是当我运行它时,它说"malloc failed !!!".据我计算,只需要大约11GB的内存来容纳整个阵列.在我开始代码之前,我检查了服务器,并且有110GB的可用内存.为什么会发生错误?
我还发现,如果我减少num到40000,那么malloc将会成功.
这是否意味着可以分配的最大内存有限制malloc()?
而且,如果我改变分配方式,直接声明这样大小的2D float数组,如下:
int main(int argc, char const *argv[])
{
int num = 56120,i,j;
float ls[3149454400];
if(ls == NULL){
cout << "malloc failed !!!" << endl;
while(1);
}
cout << "malloc succeeded ~~~" << endl;
for(i = num - 10 ; i < num; i ++){
for( j = num - 10; j < num ; j++){
ls[i*num + j] = 1;
}
}
for(i = num - 11 ; i < num; i ++){
for( j = num - 11; j < num ; j++){
cout << ls[i*num + j] << endl;
}
}
return 0;
}
Run Code Online (Sandbox Code Playgroud)
然后我编译并运行它.我得到了"Segmentation fault".
我怎么解决这个问题?
Ctx*_*Ctx 22
问题是,你的计算
(num * num) * sizeof(float)
Run Code Online (Sandbox Code Playgroud)
以32位有符号整数计算完成,num = 56120的结果为
-4582051584
Run Code Online (Sandbox Code Playgroud)
然后将其解释为size_t,其值非常大
18446744069127500032
Run Code Online (Sandbox Code Playgroud)
你没有那么多内存;)这就是malloc()失败的原因.
铸造num于size_t中的malloc计算,则预期它应该工作.
正如其他人所指出的那样,在OP的平台上56120*56120溢出int数学.那是未定义的行为(UB).
malloc(size_t x)接受一个size_t参数,传递给它的值最好使用至少size_t数学计算.通过反转乘法顺序,这就完成了. 至少在乘法之前扩大到sizeof(float) * num原因.numsize_t
int num = 56120,i,j;
// ls = (float *)malloc((num * num)*sizeof(float));
ls = (float *) malloc(sizeof(float) * num * num);
Run Code Online (Sandbox Code Playgroud)
即使这会阻止UB,但这并不能防止溢出,因为数学上 sizeof(float)*56120*56120可能仍会超出SIZE_MAX.
代码可以预先检测潜在的溢出.
if (num < 0 || SIZE_MAX/sizeof(float)/num < num) Handle_Error();
Run Code Online (Sandbox Code Playgroud)
无需投射结果malloc().
使用引用变量的大小比调整类型更容易编码和维护.
什么时候num == 0,malloc(0) == NULL不一定是内存不足.
全部一起:
int num = 56120;
if (num < 0 || ((num > 0) && SIZE_MAX/(sizeof *ls)/num < num)) {
Handle_Error();
}
ls = malloc(sizeof *ls * num * num);
if (ls == NULL && num != 0) {
Handle_OOM();
}
Run Code Online (Sandbox Code Playgroud)
int num = 56120,i,j;
ls = (float *)malloc((num * num)*sizeof(float));
Run Code Online (Sandbox Code Playgroud)
num*num是56120*56120哪个3149454400溢出signed int导致未定义的行为.
40000工作的原因是40000*40000可以表示为int.
更改num为long long(或甚至unsigned int)的类型
小智 6
这与其他人编写的内容形成对比,但对我来说,将变量num更改为size_t可以进行分配.可能是num*num溢出了malloc的int.使用56120*56120而不是num*num执行malloc应该抛出溢出错误.