I\'m using a server with 128GB memory to do some computation. I need to malloc()
a 2D float array of size 56120 * 56120. An example code is as follows:
As other have pointed out, 56120*56120
overflows int
math on OP's platform. That is undefined behavior (UB).
malloc(size_t x)
takes a size_t
argument and the values passed to it is best calculated using at least size_t
math. By reversing the multiplication order, this is accomplished. sizeof(float) * num
cause num
to be widened to at least size_t
before the multiplication.
int num = 56120,i,j;
// ls = (float *)malloc((num * num)*sizeof(float));
ls = (float *) malloc(sizeof(float) * num * num);
Even though this prevents UB, This does not prevent overflow as mathematically sizeof(float)*56120*56120
may still exceed SIZE_MAX
.
Code could detect potential overflow beforehand.
if (num < 0 || SIZE_MAX/sizeof(float)/num < num) Handle_Error();
No need to cast the result of malloc()
.
Using the size of the referenced variable is easier to code and maintain than sizing to the type.
When num == 0
, malloc(0) == NULL
is not necessarily an out-of-memory.
All together:
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();
}
The problem is, that your calculation
(num * num) * sizeof(float)
is done as 32-bit signed integer calculation and the result for num=56120 is
-4582051584
Which is then interpreted for size_t with a very huge value
18446744069127500032
You do not have so much memory ;) This is the reason why malloc()
fails.
Cast num
to size_t
in the calculation of malloc, then it should work as expected.
float ls[3149454400];
is an array with automatic storage type, which is usually allocated on the process stack. A process stack is limited by default by a value much smaller than 12GB you are attempting to push there. So the segmentation fault you are observing is caused by the stack overflow, rather than by the malloc
.
int num = 56120,i,j;
ls = (float *)malloc((num * num)*sizeof(float));
num
* num
is 56120*56120
which is 3149454400
which overflows a signed int
which causes undefined behavoir.
The reason 40000 works is that 40000*40000 is representable as an int.
Change the type of num
to long long
(or even unsigned int
)
This is in contrast to what others have written, but for me, changing the variable num to size_t from int allows allocation. It could be that num*num overflows the int for malloc. Doing malloc with 56120 * 56120 instead of num*num should throw an overflow error.