C 如果我增加条目数,memmove会导致分段错误

C 如果我增加条目数,memmove会导致分段错误,c,mpi,C,Mpi,下午好,如果我将nx、ny和nz推到某个阈值以上,例如100,则会出现以下错误 Primary job terminated normally, but 1 process returned a non-zero exit code. Per user-direction, the job has been aborted. mpiexec noticed that process rank 0 with PID 0 on node debian exited on signal 11 (Se

下午好,如果我将nx、ny和nz推到某个阈值以上,例如100,则会出现以下错误

Primary job terminated normally, but 1 process returned a non-zero exit code. 
Per user-direction, the job has been aborted.
mpiexec noticed that process rank 0 with PID 0 on node debian exited on signal 11 (Segmentation fault).
如果我保持在阈值以下,一切正常

生成错误的代码段位于以下函数中:

void dealiasing(int nx, int ny, int nz, int nxd, int nzd, FFT_SCALAR *U) {

int nz_left = 1+ (nz-1)/2 ;
int i, stride_y, stride_z, reader=0, last_index;
for ( stride_z = 0; stride_z < nz_left*ny*nxd*2; stride_z = stride_z + ny*nxd*2) {
    for ( stride_y = 0; stride_y < ny*nxd*2; stride_y = stride_y + nxd*2) {
        for ( i = 0; i < (nx)*2; i++) {
            U[reader] = U[stride_z + stride_y+i];
            reader++;
        }
    }
    last_index = stride_z + stride_y;
}

for ( stride_z = (nzd - nz_left+1)*nxd*ny*2; stride_z < nzd*ny*nxd*2; stride_z = stride_z + ny*nxd*2) {
    for ( stride_y = 0; stride_y < ny*nxd*2; stride_y = stride_y + nxd*2) { 
        for ( i = 0; i < (nx)*2; i++) {
            U[reader] = U[stride_z + stride_y+i];
            reader++;
        }
    }
    last_index = stride_z + stride_y;
}


//Save positive modes
double U_pos[2*nx*ny*(1+(nz-1)/2)];
memmove(U_pos, U, sizeof(FFT_SCALAR)*2*nx*ny*(1+(nz-1)/2)); 
memmove(U, &U[2*nx*ny*(1+(nz-1)/2)], sizeof(FFT_SCALAR)*2*nx*ny*((nz-1)/2));
memmove(&U[2*nx*ny*((nz-1)/2)], U_pos, sizeof(FFT_SCALAR)*2*nx*ny*(1+(nz-1)/2));

如果我重写这些行:

double U_pos[2*nx*ny*(1+(nz-1)/2)];
memmove(U_pos, U, sizeof(FFT_SCALAR)*2*nx*ny*(1+(nz-1)/2)); 

似乎您覆盖了内存—除非
sizeof(FFT\U SCALAR)
为1—因为您将更多的字节移到
U\U pos
中,使其无法容纳


另一个问题可能是
U_pos
是(在大多数实现中)将在堆栈上分配的VLA。随着
nx
ny
nz
变大,U\U pos阵列变大,可能会出现堆栈溢出。

如果我将这些行重写为:

double U_pos[2*nx*ny*(1+(nz-1)/2)];
memmove(U_pos, U, sizeof(FFT_SCALAR)*2*nx*ny*(1+(nz-1)/2)); 

似乎您覆盖了内存—除非
sizeof(FFT\U SCALAR)
为1—因为您将更多的字节移到
U\U pos
中,使其无法容纳


另一个问题可能是
U_pos
是(在大多数实现中)将在堆栈上分配的VLA。随着
nx
ny
nz
变大,U\U pos数组变大,可能会出现堆栈溢出。

逐步使用调试器并检查值。我们没有这样的可能性,特别是在缺少的情况下。问题是什么?如果valgrind可用于您的OS/CPU,那么问题是“为什么如果我将nx,ny,nz值推到100以上,我会遇到这种分段错误?为什么不在下面?”是否有足够的堆栈用于
双U位置[2*nx*ny*(1+(nz-1)/2)]?它可能需要大约8MB的内存。请逐步使用调试器并检查值。我们没有这样的可能性,特别是在缺少的情况下。问题是什么?如果valgrind可用于您的OS/CPU,那么问题是“为什么如果我将nx,ny,nz值推到100以上,我会遇到这种分段错误?为什么不在下面?”是否有足够的堆栈用于
双U位置[2*nx*ny*(1+(nz-1)/2)]?它可能需要大约8MB。正如你告诉我的,很可能是堆栈溢出,因为数组太大了。我能做些什么来避免它?我读过,在阵列上进行动态分配可能会有所帮助,是真的吗?很抱歉提出这些问题,但我是个新手,我正在努力了解我的缺点和缺点在哪里why@Mirco是的,动态分配更适合于大型阵列。比如:
double*U_pos=malloc(你需要的元素*sizeof*U pos)
@Mirco Try
double*U_pos=malloc(sizeof(*U_pos)*一些大小)别忘了做
免费(U_pos)位于函数末尾。其余的都应该是一样的。在运行应用程序之前,您可以尝试
ulimit-s
。正如您告诉我的,可能是堆栈溢出,因为数组太大了。我能做些什么来避免它?我读过,在阵列上进行动态分配可能会有所帮助,是真的吗?很抱歉提出这些问题,但我是个新手,我正在努力了解我的缺点和缺点在哪里why@Mirco是的,动态分配更适合于大型阵列。比如:
double*U_pos=malloc(你需要的元素*sizeof*U pos)
@Mirco Try
double*U_pos=malloc(sizeof(*U_pos)*一些大小)别忘了做
免费(U_pos)位于函数末尾。其余的都应该相同。在运行应用程序之前,您可以尝试
ulimit-s
#define SOME_SIZE (2*nx*ny*(1+(nz-1)/2))

double U_pos[SOME_SIZE];
memmove(U_pos, U, sizeof(FFT_SCALAR)*SOME_SIZE);