C语言OpenMP环境下结构体数组创建销毁的内存问题排查
OpenMP并行段错误排查与测试代码验证
问题背景与现象
我在C代码的串行部分动态分配了结构体CONF的二维数组:
CONF **conf = (CONF **) malloc (Nc*sizeof(CONF *));
Nc为运行时获取的变量,每个conf[i]的大小存储在long int数组Nc_size中,随后逐个分配conf[i]:
for (i=0; i<Nc; i++) { long int sz; // 除最后一个外的所有元素 if (i+1!=Nc) { sz = MC; } // 最后一个元素 else { sz = conflistd%MC; } Nc_size[i] = sz; (conf)[i] = (CONF *) malloc(sz*sizeof(CONF)); }
CONF是包含动态double数组的复杂结构体,填充完成后,我尝试通过OpenMP并行调用CLUSTERINGL函数修改每个conf[i]:
#pragma omp parallel private(i, NIR) shared(conf, Nc_size) { #pragma omp for for (i=0; i<Nc; i++) { conf[i] = CLUSTERINGL (conf[i], &sz, ...); } }
CLUSTERINGL函数会创建更小的CONF结构体数组,填充原数组的子集后返回,同时释放原conf[i]及其内部资源:
CONF *CLUSTERINGL(CONF *conflist1, long int *conflist1d, ...) { CONF *conflist3 = malloc(1 * sizeof(CONF)); for (j = 0; j < k; j++) { if (arrayofconf[j][0] > -1) { long int NFR = conflist1[j].NFR; i = arrayofconf[j][0]; // 若为最接近质心的元素 conflist3 = (CONF *)realloc(conflist3, (conflist3d + 1) * sizeof(CONF)); conflist3[conflist3d].IR = malloc(NIR * sizeof(double)); conflist3[conflist3d].angles = malloc(NBONDS * sizeof(double)); conflist3[conflist3d].TR = malloc(3 * (NFR + 1) * sizeof(double)); conflist3[conflist3d].ROT = malloc(3 * (NFR + 1) * sizeof(double)); conflist3d++; } } // ... 省略中间业务逻辑 for (i = 0; i < *conflist1d; i++) { if (NIR != 0) { free(conflist1[i].IR); } free(conflist1[i].angles); free(conflist1[i].TR); free(conflist1[i].ROT); } free(conflist1); *conflist1d = conflist3d; return conflist3; }
串行运行时一切正常,但并行模式下几乎每次都会出现段错误。我猜测可能是向CLUSTERINGL传递conf[i]时需要加&符号,特寻求排查建议。
简化测试代码验证请求
我编写了简化的测试代码,编译命令为gcc main.c -fopenmp -lm,执行命令./a.out 10000000,运行稳定,请求确认该测试代码的概念正确性:
maintypes.h
#include <inttypes.h> typedef struct { long int N; double *IR; } CONF;
main.c
#include <stdio.h> #include <stdlib.h> #include <math.h> #include <stdbool.h> #include "maintypes.h" #include <string.h> #include <ctype.h> #include <omp.h> #include <time.h> CONF *CLUSTERINGL (CONF *conf1, long int *conf1d, long int NIR); int main (int argc, char *argv[]) { // 检查是否传入参数 if (argc < 2) { printf ("%s","Please, give the number NA\n"); exit(0); } long int conflistd = atoi(argv[1]); long int MC = 100; long int NIR = 30; long int Nc = conflistd/MC + 1; long int Nc_size[Nc]; // CONF **conf = (CONF **) malloc (Nc*sizeof(CONF *)); // 循环变量 long int i=0, j=0; long int count=0; for (i=0; i<Nc; i++) { long int sz; // 除最后一个外的所有元素 if (i+1!=Nc) { sz = MC; } // 最后一个元素 else { sz = conflistd%MC; } Nc_size[i] = sz; (conf)[i] = (CONF *) malloc(sz*sizeof(CONF)); for (j=0;j<sz;j++) { conf[i][j].N = count; conf[i][j].IR = malloc(NIR*sizeof(double)); for (long int m=0;m<NIR;m++) { conf[i][j].IR[m] = 1.33*m; } count = count + 1; } } printf ("Starting parallel\n"); #pragma omp parallel private(i) shared (conf, Nc_size, Nc, NIR) default(none) { #pragma omp for for (i=0;i<Nc;i++) { long int sz = Nc_size[i]; if (sz>4) { conf[i] = CLUSTERINGL(conf[i], &sz, NIR); Nc_size[i] = sz; } } } return 0; } CONF *CLUSTERINGL (CONF *conf1, long int *conf1d, long int NIR) { long int d = *conf1d/3; CONF *confnew = (CONF *) malloc (d*sizeof(CONF)); long int j=0; for (j=0;j<d;j++) { confnew[j].N = conf1[j].N; confnew[j].IR = malloc(NIR*sizeof(double)); for (long int m=0;m<NIR;m++) { confnew[j].IR[m] = pow(sqrt(conf1[j].IR[m])*5*j,1.8); confnew[j].IR[m]*5; confnew[j].IR[m]*confnew[j].IR[m]; } } // 清理资源 for (j=0;j<*conf1d;j++) { free (conf1[j].IR); } free (conf1); *conf1d=d; return confnew; }
内容的提问来源于stack exchange,提问作者user3590300
相关产品推荐
相关产品推荐

