BAD TERMINATION OF ONE OF YOUR APPLICATION PROCESSES EXIT CODE: 139

好气好气好气!
为了记录这次痛点,时隔这么久再次更新文章!

1.报错问题

在mpi编程时遇到这个问题:

===================================================================================
=   BAD TERMINATION OF ONE OF YOUR APPLICATION PROCESSES
=   EXIT CODE: 139
=   CLEANING UP REMAINING PROCESSES
=   YOU CAN IGNORE THE BELOW CLEANUP MESSAGES
===================================================================================
YOUR APPLICATION TERMINATED WITH THE EXIT STRING: Segmentation fault (signal 11)
This typically refers to a problem with your application.
Please see the FAQ page for debugging suggestions

2.原(报错)代码

#include <iostream>
#include <mpi.h>
using namespace std;

int main(int argc, char* argv[]) {
    int rank, size;
    MPI_Init(&argc, &argv);    
    MPI_Comm_rank(MPI_COMM_WORLD, &rank);      
    MPI_Comm_size(MPI_COMM_WORLD, &size);    

    if (rank == 0) {
        int num_row = 1;
        double x[] = { 1.0, 2.0 ,3.0 };
        double b[] = { 1.0, 2.5, 5.3, 3.1 };
        for (int cur_tid = 1; cur_tid < size; cur_tid++)
        {
            MPI_Send(&num_row, 1, MPI_INT, cur_tid, 0, MPI_COMM_WORLD);
            MPI_Send(&(x[0]), 3, MPI_DOUBLE, cur_tid, 0, MPI_COMM_WORLD);
            MPI_Send(&(b[0]), 4, MPI_DOUBLE, cur_tid, 0, MPI_COMM_WORLD);
        }
    }
    else {
        int num_row = 0;
        double* x = new double(3);
        double* b = new double(4);
        MPI_Recv(&num_row, 1, MPI_INT, 0, 0, MPI_COMM_WORLD, MPI_STATUS_IGNORE);  
        MPI_Recv(&(x[0]), 3, MPI_DOUBLE, 0, 0, MPI_COMM_WORLD, MPI_STATUS_IGNORE);
        MPI_Recv(&(b[0]), 5, MPI_DOUBLE, 0, 0, MPI_COMM_WORLD, MPI_STATUS_IGNORE);

        cout << "I am thread " << rank << " and the num_row is " << num_row << endl;
        cout << "I am thread " << rank << " and x1 is " << x[1] << endl;
        cout << "I am thread " << rank << " and b1 is " << b[1] << endl;
    }
    MPI_Barrier(MPI_COMM_WORLD);
    MPI_Finalize();
    return 0;
}

3.报错原因

经多方查找,并未找到解决方案。

在该链接(需科学上网)上看到说MPI_Recv()接收的元素太多了。但是我并没有get到这个作者的点。现在恍然大悟。

今天看到一篇文章才发现,原来我在非0进程中定义了一个错误的变量,其中double* x = new double(3)表示动态分配一个double型存储单元,将这个单元地址赋给x,即x指向这个单元。 而我的本意是定义一个大小为3的数组!

所以应该修改为double *x=new double[3]。这样才表明是申请3个double型存储单元!!!

简言之,我的错误原因是没有分清double* x = new double(3)double* x = new double[3]的区别。修改完成后,MPI_Recv()接收的元素和MPI_Send()发送的元素就匹配上了,也就不存在内存溢出的错误了。

4.修改后(正确)代码

#include <iostream>
#include <mpi.h>
using namespace std;

int main(int argc, char* argv[]) {
    int rank, size;
    MPI_Init(&argc, &argv);    
    MPI_Comm_rank(MPI_COMM_WORLD, &rank);      
    MPI_Comm_size(MPI_COMM_WORLD, &size);    

    if (rank == 0) {
        int num_row = 1;
        double x[] = { 1.0, 2.0 ,3.0 };
        double b[] = { 1.0, 2.5, 5.3, 3.1 };
        for (int cur_tid = 1; cur_tid < size; cur_tid++)
        {
            MPI_Send(&num_row, 1, MPI_INT, cur_tid, 0, MPI_COMM_WORLD);
            MPI_Send(&(x[0]), 3, MPI_DOUBLE, cur_tid, 0, MPI_COMM_WORLD);
            MPI_Send(&(b[0]), 4, MPI_DOUBLE, cur_tid, 0, MPI_COMM_WORLD);
        }
    }
    else {
        int num_row = 0;
        double* x = new double[3];//注意,就是这一行
        double* b = new double[4];//注意,就是这一行
        MPI_Recv(&num_row, 1, MPI_INT, 0, 0, MPI_COMM_WORLD, MPI_STATUS_IGNORE);  
        MPI_Recv(&(x[0]), 3, MPI_DOUBLE, 0, 0, MPI_COMM_WORLD, MPI_STATUS_IGNORE);
        MPI_Recv(&(b[0]), 5, MPI_DOUBLE, 0, 0, MPI_COMM_WORLD, MPI_STATUS_IGNORE);

        cout << "I am thread " << rank << " and the num_row is " << num_row << endl;
        cout << "I am thread " << rank << " and x1 is " << x[1] << endl;
        cout << "I am thread " << rank << " and b1 is " << b[1] << endl;
    }
    MPI_Barrier(MPI_COMM_WORLD);
    MPI_Finalize();
    return 0;
}

5.总结

如果你的错误和我不一样,那一定要好好检查发送和接受的大小问题,本质上应该是一致的。这个错误烦了我好几天,一直没找到原因,最终发现是我的基础没打牢,错误居然就是一个中括号和小括号的区别,还需要继续努力呀!

转载请注明来源https://blog.csdn.net/qq_44273006/article/details/122024821

  • 5
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值