【问题标题】:This program keeps giving me the message the error *** glibc detected *** double free or corruption (fasttop)这个程序不断给我消息错误***检测到glibc ***双重免费或损坏(fasttop)
【发布时间】:2021-12-28 11:56:52
【问题描述】:

我有一个程序可以计算间隔 (definition) 之间的“快乐数字”。我必须以两种方式编写它,第一种必须是顺序的,第二种必须是并行的。第一个程序完成了,我所做的只是在并行版本中添加了一个特定于 omp 的行。问题是,每次运行它都会给我这个错误:*** glibc detected *** ./p: double free or corruption (fasttop): 然后打印“回溯”和“内存映射”。我认为这与我调用的 malloc 和 realloc 有关,但不知道是什么。你能帮我解决这个问题吗?

#include <stdio.h>
#include <omp.h>
#include <sys/time.h>
#include <math.h>

#define LLI long long int

int length(LLI n) {
    int len = 0;
    while (n != 0) {
        n /= 10;
        len++;
    }
    return len;
}

void breakdown(int *a, LLI n, int len) {
    int i;
    for (i = len - 1; i >= 0; i--) {
        a[i] = n % 10;
        n /= 10;
    }
}

int calculate(int *a, int* len) {
    int i, sum = 0;
    for (i = 0; i < *len; i++) {
        sum += pow(a[i], 2);
    }
    if (sum < 10) {
        *len = 1;
    } else {
        *len = length(sum);
        breakdown(a, sum, *len);
    }
    return sum;
}

int calculateHappy(int *a, int len) {
    int sum;
    do {
        sum = calculate(a, &len);
    } while (len != 1);
    if (sum == 1) {
        return 1;
    }
    return 0;
}

int main(int argc, const char* argv[]) {
    if (argc != 4) {
        printf("man no good bro i ned 3 parameter\np: interval left border\nq: interval right border\nthreadNr: think bro think what could it be\n");
        exit(0);
    }

    LLI p, q, i, *result;
    int *a, len, j, happyNr = 0, threadNr;
    p = atoll(argv[1]);
    q = atoll(argv[2]);
    threadNr = atoi(argv[3]);
    result = (LLI*) malloc (1 * sizeof(LLI));
    if (p >= q) {
        printf("man no good bro p < q man\n");
        exit(0);
    }
    struct timeval start, stop;
    gettimeofday(&start, NULL);
    #pragma omp parallel for num_threads(threadNr) shared (happyNr, result)
    for (i = p; i < q; i++) {
        printf("%d. thread: i am at %d\n", omp_get_thread_num(), i);
        len = length(i);
        a = (int*) malloc (len * sizeof(int));
        breakdown(a, i, len);
        if (calculateHappy(a, len)) {
            happyNr++;
            result = (LLI*) realloc (result, happyNr * sizeof(LLI));
            result[happyNr - 1] = i;
        }
    }
    gettimeofday(&stop, NULL);

    printf("The program took %d seconds/%d microseconds to run\n", stop.tv_sec - start.tv_sec, stop.tv_usec - start.tv_usec);
    FILE *f = fopen("output.txt", "w");
    if (happyNr != 0) {
        fprintf(f, "The happy numbers are: \n");
        for (i = 0; i < happyNr; i++) {
            fprintf(f, "%lli ", result[i]);
        }
        fprintf(f,"\n");
    } else {
        fprintf(f, "In the interval [%lli, %lli] there are no happy numbers.\n", p, q);
    }
    free(result);
    return 0;
}

我运行代码的命令是gcc main.c -o p -fopenmp,然后是./p 1 100 5,但错误发生在任意数量的线程(当然除了1)。

【问题讨论】:

  • printf("%d. thread: i am at %d\n", omp_get_thread_num(), i); 中应该是 ...i am at %lld...printf("The program took %d seconds/%d microseconds to run\n", stop.tv_sec - start.tv_sec, stop.tv_usec - start.tv_usec); 应该是 program took %ld... 首先修复这些,错误的 printf 说明符会导致未定义的行为。顺便说一句,彩色错误消息;)
  • 我刚才评论了那部分。仍然不起作用,大多数时候我得到Aborted (core dumped) 或分段错误
  • 如果这有帮助,我收到的其他 glibc detected 消息是 realloc(): invalid next sizemalloc(): invalid next size
  • 尝试在循环内声明aint *a = (int*) malloc (len * sizeof *a); 当然删除之前的声明。
  • 是的,它们并没有消失,肯定有问题,不幸的是我现在没有时间,尝试使用 valgrind,彻底调试也可能会有所帮助

标签: c linux parallel-processing openmp glibc


【解决方案1】:

问题是你有使用共享变量lenahappyNr 和数组result 的数据竞争。变量lena 必须定义为私有,happyNr 的增加和result 的重新分配必须受到保护。只需添加几行 OpenMP 代码,您的程序就可以了(但不是很快,请参见下面的 cmets):

    #pragma omp parallel for default(none) private(i, len, a) num_threads(threadNr) shared (happyNr, result, p, q)
    for (i = p; i < q; i++) {
        printf("%d. thread: i am at %lld\n", omp_get_thread_num(), i);
        len = length(i);
        a = (int*) malloc (len * sizeof(int));
        breakdown(a, i, len);
        if (calculateHappy(a, len)) {
            #pragma omp critical
            {
                happyNr++;
                result = (LLI*) realloc (result, happyNr * sizeof(LLI));
                result[happyNr - 1] = i;
            }
        }
        free(a);
    }

注意:

  1. 您忘记释放a。在循环中分配和释放内存不是一个好主意。如果速度是一个问题,你应该重写它(例如,只使用int a[(int) log10(LLONG_MAX)+1];)。 (可能是你的功课,所以根本不重要。)
  2. 数组result 的连续重新分配非常慢,需要使用critical 部分(即锁)。分配一个足够大的数组来存储所有数据会更好,在这种情况下,您不必使用critical 部分(原子操作或归约就足够了)并且您的程序可能运行得更快。
  3. 始终在所需的最低范围内定义变量。在 OpenMP 代码中避免数据竞争尤为重要,因为在并行区域内定义的变量默认是私有的。另一方面也有助于编译器进行更好的优化。
  4. 使用a[i]*a[i] 而不是pow(a[i], 2),因为整数乘法比浮点函数pow 快得多。

综合起来:

int calculate(int *a, int* len) {
...
        sum += a[i]*a[i];
...
}  

int main(int argc, const char* argv[]) {

    const int max_a_size=(int) log10(LLONG_MAX)+1;
    ...
    LLI* result = (LLI*) malloc ((q-p) * sizeof(LLI));
    //check for memory allocation problems here

    struct timeval start, stop;
    gettimeofday(&start, NULL);
    #pragma omp parallel for num_threads(threadNr) default(none) shared(happyNr, result,p,q)
    for (LLI i = p; i < q; i++) {
        int len = length(i);
        int a[max_a_size];
        breakdown(a, i, len);
        if (calculateHappy(a, len)) {
            int old_happyNr;
            #pragma omp atomic capture          
            old_happyNr=happyNr++;     
            result[old_happyNr] = i;            
        }
    }
    gettimeofday(&stop, NULL);

    printf("The program took %f seconds to run on %d threads\n", stop.tv_sec- start.tv_sec+ (stop.tv_usec- start.tv_usec)/1000000.0, threadNr);
    printf("There are %d happy numbers between %lld and %lld. \n", happyNr, p,q);

...
}

它可以很好地适应线程数,在我的笔记本电脑上我得到了以下结果:

g++-11 2.cpp -fopenmp -O3 -mavx2 -Wall && time ./a.out
The program took 1.254470 seconds to run on 8 threads
There are 14255378 happy numbers between 1 and 100000000.

real    0m1.260s
user    0m9.088s
sys     0m0.389s


The program took 7.132763 seconds to run on 1 threads
There are 14255378 happy numbers between 1 and 100000000.

real    0m7.138s
user    0m7.124s
sys     0m0.010s

【讨论】:

    猜你喜欢
    • 2013-09-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-10-01
    • 1970-01-01
    相关资源
    最近更新 更多