C 如果我增加条目数,memmove会导致分段错误
下午好,如果我将nx、ny和nz推到某个阈值以上,例如100,则会出现以下错误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
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 Trydouble*U_pos=malloc(sizeof(*U_pos)*一些大小)代码>别忘了做免费(U_pos)代码>位于函数末尾。其余的都应该是一样的。在运行应用程序之前,您可以尝试ulimit-s
。正如您告诉我的,可能是堆栈溢出,因为数组太大了。我能做些什么来避免它?我读过,在阵列上进行动态分配可能会有所帮助,是真的吗?很抱歉提出这些问题,但我是个新手,我正在努力了解我的缺点和缺点在哪里why@Mirco是的,动态分配更适合于大型阵列。比如:double*U_pos=malloc(你需要的元素*sizeof*U pos)
@Mirco Trydouble*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);