在将值分配给正确分配的数组时,我遇到了分段错误。以下是代码:
int SpV = L*L*L;
int V = SpV*T;
int M = 16;
int Ns = 2;
int Np = 10;
float *twopBuf = (float*) malloc(Np*Ns*V*M*2*sizeof(float));
if(twopBuf == NULL){
fprintf(stderr,"Cannot allocate twopBuf. Exiting\n");
exit(-1);
}
for(int bar=0;bar<Np;bar++)
for(int pr=0;pr<Ns;pr++)
for(int t=0;t<T;t++)
for(int v=0;v<SpV;v++)
for(int gm=0;gm<M;gm++){
int pos = 2*gm + 2*M*v + 2*M*SpV*t + 2*M*SpV*T*pr + 2*M*SpV*T*Ns*bar;
twopBuf[ 0 + pos ] = 1.0; // Set to 1.0 for
twopBuf[ 1 + pos ] = 1.0; // testing purposes
}
输入L和T,所以说L = 32
和T = 64
时运行正常。但是对于L = 48
和T = 96
,我会在bar
变为2并且在它变为3之前出现分段错误。如果没有足够的内存来分配twopBuf
那么&#39 ; t我已经收到错误消息了吗?
我在大型超级计算机的头节点上运行它,如果它有所不同。感谢。
答案 0 :(得分:5)
表达式
Np*Ns*V*M*2*sizeof(float)
评估为
((((Np*Ns)*V)*M)*2)*sizeof(float)
由于C和C ++中*
的从左到右的关联性。参见C11标准草案n1570, 6.5.5乘法运算符。
表达式E1 * E2
的类型是操作数的常见实际类型( 6.3.1.8常规算术转换)。在这种情况下,类型是
((((int*int)*int)*int)*int)*size_t
所以除了最后一次乘法之外,其余都是int
- 精度和范围。
对于L = 48,T = 96和sizeof(float) == 4
,int
- 精度乘法的无限精确结果为6794772480
,这在16位或32位{{1}中无法表示因此,其中一个乘法必须在这样的实现上溢出,这是未定义的行为。
如果表达式重新排序为:
int
所有乘法都以sizeof(float)*Np*Ns*V*M*2
精度完成,除非size_t
可以表示int
可以表示的所有值。如果乘法是以size_t
- 精度完成的,则即使乘法溢出,乘法也是明确定义的,因为size_t
是无符号的。但是,如果 溢出,size_t
将返回一个明显小于您预期的分配,如果您访问超出分配对象的末尾,则会导致未定义的行为。
对于您提供的数字,如果malloc()
的填充位少于30,则64位size_t
不会溢出。