0

In my C program I have a structure like the one below

#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <mpi.h>

typedef struct Message
{
    int elemNr;
    char *elem;
} Msg;

I think I made all the steps to create custom data type in MPI

int main(int argc, char **argv) {
    int size, rank;
    int i;

    MPI_Init(&argc, &argv);
    MPI_Comm_size(MPI_COMM_WORLD, &size);
    MPI_Comm_rank(MPI_COMM_WORLD, &rank);

    if (size < 2) {
        fprintf(stderr,"Requires at least two processes.\n");
        exit(-1);
    }

    // just for simplicity
    const int n = 5;

    // create a new type for struct message
    MPI_Datatype myType;
    Msg msgSnd;

    int block_length[2] = {1, n};

    MPI_Aint elemNrAddr, elemAddr;
    MPI_Aint displacement[2] = {0, 0};
    MPI_Get_address(&msgSnd.elemNr, &elemNrAddr);
    MPI_Get_address(&msgSnd.elem, &elemAddr);

    // just displacement[1] because displacement[0] starts from 0
    displacement[1] = elemAddr - elemNrAddr;
    
    MPI_Datatype types[2] = {MPI_INT, MPI_CHAR};

    MPI_Type_create_struct(2, block_length, displacement, types, &myType);
    MPI_Type_commit(&myType);

    // populate the message
    msgSnd.elemNr = n;
    msgSnd.elem = malloc(sizeof(char) * msgSnd.elemNr);

    srand(time(NULL));
    for (i = 0; i < msgSnd.elemNr; i++)
        msgSnd.elem[i] = rand() % 26 + 'a';

    if (rank != 0) {
        printf("I'm sending\n");
        MPI_Send(&msgSnd, 1, myType, 0, 0, MPI_COMM_WORLD);
        printf("I sent\n");
    } else {
        MPI_Status status;
        Msg msgRcv;
  
        printf("I'm receiving\n");
        MPI_Recv(&msgRcv, 1, myType, 1, 0, MPI_COMM_WORLD, &status);
        printf("I received\n");

        for (i = 0; i < msgRcv.elemNr; i++)
            printf("element %d: %c\n", i, msgRcv.elem[i]);
    
        if (msgRcv.elem != NULL)
            free(msgRcv.elem);        
    }

    if (msgSnd.elem != NULL)
        free(msgSnd.elem);

    MPI_Type_free(&myType);
    MPI_Finalize();

    return 0;
}

I ran the above code, but unfortunately when process 0 receives the message, the elem pointer points to null and the program ends with segmentation fault.

Can you help me to find the problem? Or, how can I send a dynamic array inside a struct on MPI?

  • msgRcv[i].elem should probably be msgRecv.elem[i]. I'm surprised this actually compiles. – pmacfarlane Nov 18 '22 at 13:53
  • 1. `MPI_Get_address(&msg.elem, &elemAddr);` gives you the location of the pointer, not of the data 2. Maybe the Struct type will work, but there i a `hindexed` type that is for dealing with absolute addresses. – Victor Eijkhout Nov 18 '22 at 13:54
  • I think you should post a [minimal, reproducible example](https://stackoverflow.com/help/minimal-reproducible-example), so we can try to compile it ourselves, and so you can verify that it compiles for you. The code above does not compile, even after fixing obvious things like adding missing header files. – pmacfarlane Nov 18 '22 at 14:20
  • have a look at https://stackoverflow.com/questions/74110896/allocating-dynamic-array-of-structs-with-dynamic-arrays-in-c – Gilles Gouaillardet Nov 18 '22 at 15:36
  • I'm sorry, yesterday I wrote a very bad code, now I fixed the errors and added all the pieces you need to test it. –  Nov 19 '22 at 09:22

0 Answers0