【问题标题】:Abnormal Behaviour string MPI_Send() and MPI_Recv()异常行为字符串 MPI_Send() 和 MPI_Recv()
【发布时间】:2019-01-14 13:32:33
【问题描述】:

我的程序正在编译并显示异常行为。

使用以下命令进行编译

mpicc one.c -o one

mpiexec -n 2 ./one

我尝试调试它,但没有显示编译错误。 我不明白为什么我的程序行为异常

#include<mpi.h>
#include<stdio.h>
#include<string.h>
int main(int argc,char * argv[])
{

    char str[434];
    int n;
    int rank,size; MPI_Status status;

    MPI_Init(&argc,&argv);
    MPI_Comm_rank(MPI_COMM_WORLD,&rank);
    MPI_Comm_size(MPI_COMM_WORLD,&size);
    if(rank == 0)
    {//Sender process
        scanf("%s",&str);

        MPI_Ssend(&n,1,MPI_INT,1,0,MPI_COMM_WORLD);
        MPI_Ssend(&str,n,MPI_CHAR,1,0,MPI_COMM_WORLD);
        printf("Sending word %s in process 0\n",str);
    }
    else
    {//Receiver process
        MPI_Recv(&n,1,MPI_INT,0,0,MPI_COMM_WORLD,&status);
        MPI_Recv(&str,n,MPI_CHAR,0,0,MPI_COMM_WORLD,&status);
        printf("Receiving word %s in process 1\n",str);
    }
    MPI_Finalize();


    return 0;
}

输入:

哈哈

实际结果

在进程0中发送单词哈哈

在过程1中接收单词haha

交换结果

在进程0中发送单词哈哈

在进程1中接收字��������

【问题讨论】:

  • 启用编译器警告。您正在传递一个指向数组的指针地址,例如scanf 你应该简单地将指针传递给数组str。稍后在您的代码中也会出现同样的问题。
  • 你永远不会初始化n。而且您不应该使用&amp;str,它是指向数组的指针(类型为char (*)[434])。使用&amp;str[0] 或普通str(衰减为&amp;str[0])。 &amp;str 的这种用法在你使用它的任何地方都是错误的。

标签: c mpi


【解决方案1】:

正如人们在您帖子的 cmets 中所指出的那样,您不能像以前那样使用 str,因为 scanf() 期望 char *,而您传递它时 char (*)[434],它们是不一样。

如果您使用"-Werror -Wformat" 标志编译,您会看到此错误(或警告)。

修改代码以使用指针而不是 char 数组后,如下所示:

#include<mpi/mpi.h>
#include<stdio.h>
#include<string.h>
#include <malloc.h>

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

    const int size = 434;
    char* str_send = (char*) malloc(size * sizeof(char)); // = "haha";
    char* str_recv = (char*) malloc(size * sizeof(char));
    int n = size;
    int rank;
    MPI_Status status;

    MPI_Init(&argc,&argv);
    MPI_Comm_rank(MPI_COMM_WORLD,&rank);
    MPI_Comm_size(MPI_COMM_WORLD,&size);
    if(rank == 0)
    {//Sender process
        scanf("%s", str_send);

        MPI_Ssend(&n,1,MPI_INT,1,0,MPI_COMM_WORLD);
        MPI_Ssend(str_send,n,MPI_CHAR,1,0,MPI_COMM_WORLD);
        printf("Sending word %s in process 0\n",str_send);
    }
    else
    {//Receiver process
        MPI_Recv(&n,1,MPI_INT,0,0,MPI_COMM_WORLD,&status);
        MPI_Recv(str_recv,n,MPI_CHAR,0,0,MPI_COMM_WORLD,&status);
        printf("Receiving word %s in process 1\n",str_recv);
    }
    MPI_Finalize();
    return 0;
}

它给出了输出:

junglefox@ubuntu:~/test_programs$ mpicc main.c

junglefox@ubuntu:~/test_programs$ mpiexec -n 2 ./a.out

哈哈

在进程0中发送单词哈哈

在过程1中接收单词haha

因为,我觉得您想测试 MPI 库而不是陷入其他复杂问题,我建议您使用固定输入并寻找固定输出,而不是使用 scanf .例如,

const char* str_send = "haha";

然后删除或注释掉 scanf 行。

// scanf("%s", str_send);

【讨论】:

  • 这有点矫枉过正。只需使用str 而不是&amp;str(无需更改其类型或malloc() 它)在等级0 上初始化n(例如n = strlen(str)+1)。但是如果要硬编码const char *str_send = "haha",还需要硬编码n=5
  • @GillesGouaillardet, "他有点矫枉过正。只需使用 str 而不是 &str":也许我弄错了,但 scanf 需要“@ 的地址” 987654339@" 而不是 str 本身。
  • scanf() 需要一个指向 char 的指针。 char str[16]; scanf("%s", str); 对我有效。
  • @GillesGouaillardet,是的,我同意。在这种情况下,唯一要做的就是设置n,正如您在评论中指出的那样。
猜你喜欢
  • 2017-10-25
  • 2011-11-11
  • 2014-04-17
  • 2011-01-24
  • 2016-04-22
  • 2015-05-14
  • 1970-01-01
  • 2021-05-07
  • 1970-01-01
相关资源
最近更新 更多