正确分配的数组上的分段错误

时间:2016-08-04 10:53:45

标签: c++ c

在将值分配给正确分配的数组时,我遇到了分段错误。以下是代码:

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 = 32T = 64时运行正常。但是对于L = 48T = 96,我会在bar变为2并且在它变为3之前出现分段错误。如果没有足够的内存来分配twopBuf那么&#39 ; t我已经收到错误消息了吗?

我在大型超级计算机的头节点上运行它,如果它有所不同。感谢。

1 个答案:

答案 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) == 4int - 精度乘法的无限精确结果为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不会溢出。