简体   繁体   中英

MPI_Send MPI_Recv segfault in C++

I have written a simple program in MPI, which sends and receives messages between the processors but its running with segmentation fault.

Here's my entire code

#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <string>
#include <string.h>
#include <strings.h>
#include <sstream>
#include<mpi.h>
using namespace std;
class Case {
public:
    int value;
    std::stringstream sta;
};
int main(int argc, char **argv) {
     int rank,size;
     MPI::Init(argc,argv);
     rank=MPI::COMM_WORLD.Get_rank();
     size=MPI::COMM_WORLD.Get_size();
     if(rank==0){
        Case *s=new Case();
        s->value=1;
        s->sta<<"test";
        cout<<"\nInside send before copy value  :"<<s->value;
        fflush(stdout);
        cout<<"\nInside send before copy data  :"<<s->sta.str();
        fflush(stdout);
        Case scpy;
        scpy.value=s->value;
        scpy.sta<<(s->sta).rdbuf();
        cout<<"\nInside send after copy value  :"<<scpy.value;
        cout<<"\nInside send after copy value  :"<<scpy.sta.str();
        MPI::COMM_WORLD.Send(&scpy,sizeof(Case),MPI::BYTE,1,23);
     }
     MPI::COMM_WORLD.Barrier();
     if(rank==1){
        Case r;
        MPI::COMM_WORLD.Recv(&r,sizeof(Case),MPI::BYTE,0,23);
        cout<<"\nRecieve value"<<r.value;
        fflush(stdout);
        cout<<"\nRecieve data"<<r.sta;
        fflush(stdout);
     }
     MPI::Finalize();
     return 0;
}

I got the below error message and I'm not able to figure out what is wrong in this program.
Can anyone please explain?

Inside send before copy value  :1
Inside send before copy data  :test
Inside send after copy value  :1

Recieve value1
Recieve data0xbfa5d6b4[localhost:03706] *** Process received signal ***
[localhost:03706] Signal: Segmentation fault (11)
[localhost:03706] Signal code: Address not mapped (1)
[localhost:03706] Failing at address: 0x8e1a210
[localhost:03706] [ 0] [0xe6940c]
[localhost:03706] [ 1] /usr/lib/libstdc++.so.6(_ZNSt18basic_stringstreamIcSt11char_traitsIcESaIcEED1Ev+0xc6) [0x6a425f6]
[localhost:03706] [ 2] ./a.out(_ZN4CaseD1Ev+0x14) [0x8052d8e]
[localhost:03706] [ 3] ./a.out(main+0x2f9) [0x804f90d]
[localhost:03706] [ 4] /lib/libc.so.6(__libc_start_main+0xe6) [0x897e36]
[localhost:03706] [ 5] ./a.out() [0x804f581]
[localhost:03706] *** End of error message ***
--------------------------------------------------------------------------
mpirun noticed that process rank 1 with PID 3706 on node localhost.localdomain exited on signal 11 (Segmentation fault).
-------------------------------------------------------------------------- 

Problem

I think the problem is that the line:

MPI::COMM_WORLD.Send(&scpy,sizeof(Case),MPI::BYTE,1,23);

sends a copy of the Case structure to the receiver, but it is sending a raw copy of the bytes which is not very useful. The std::stringstream class will contain a pointer to the actual memory used to store your string, so this code will:

  1. Send a pointer to the receiver (containing an address that will be meaningless to the receiver)
  2. Not send the actual contents of the string.

The receiver will seg fault when it attempts to dereference the invalid pointer.

Fix 1

One approach to fix this is to send the character data yourself.

In this approach you would send a message pointing to std::stringstream::str()::c_str() and of length std::stringstream::str()::size()*sizeof(char).

Fix 2

An alternative approach that seems to fit better with the way you are attempting to use MPI and strings is to use the Boost libraries. Boost contains functions for MPI that automatically serialize the data for you.

A useful tutorial on Boost and MPI is available on the boost website . Here is example code from that tutorial that does a similar task:

#include <boost/mpi.hpp>
#include <iostream>
#include <string>
#include <boost/serialization/string.hpp>
namespace mpi = boost::mpi;

int main(int argc, char* argv[]) 
{
  mpi::environment env(argc, argv);
  mpi::communicator world;

  if (world.rank() == 0) {
    world.send(1, 0, std::string("Hello"));
    std::string msg;
    world.recv(1, 1, msg);
    std::cout << msg << "!" << std::endl;
  } else {
    std::string msg;
    world.recv(0, 0, msg);
    std::cout << msg << ", ";
    std::cout.flush();
    world.send(0, 1, std::string("world"));
  }

  return 0;
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM