C++ 调用 RPC 函数时返回语句出现分段错误

问题描述 投票:0回答:1

当我在客户端调用 rpc 函数并发送一个整数作为参数时,服务器上的函数应该将整数转换为符号地址。当使用 callrpc 调用 RPC 函数时,整数被发送到服务器,服务器接收它,将其转换为符号地址,但在 return 语句中我遇到分段错误。

这是服务器代码:

#include <iostream>
#include <cstring>
#include <rpc/types.h>
#include <rpc/xdr.h>
#include <rpc/rpc.h>
#include <netdb.h>

char *from_number_to_symbolic(int number) {

        struct sockaddr_in temp = { AF_INET, SOCK_STREAM, { number } };
        static char symbolic[100]; 

        getnameinfo((struct sockaddr *) &temp, sizeof(struct sockaddr_in), symbolic, 100, NULL, 0, 0);
        std::cout << std::endl << symbolic << std::endl;
        return symbolic;
}

int main(int argc, char *argv[])
{
        registerrpc(42700, 1, 1,(char* (*)(char *)) from_number_to_symbolic, (xdrproc_t) xdr_int, (xdrproc_t) xdr_wrapstring);

        svc_run();
        return 0;
}

这是客户端代码:

#include <iostream>
#include <cstdlib>
#include <rpc/rpc.h>
#include <arpa/inet.h>
#include <netdb.h>

int from_numeric_to_int(char *numeric) {
        struct in_addr number;
        inet_pton(AF_INET, numeric, &number);

        return number.s_addr;
}

 

int main(int argc, char *argv[])
{
    if (argc != 2)
    {
        exit(1);
    }

    char **num_adrress = &argv[1];
    int *int_adrress = new int;

    *int_adrress = from_numeric_to_int(*num_adrress);
    char **symbolic = new char*;
   
    callrpc("127.0.0.1", 42700, 1, 1, (xdrproc_t) xdr_int, (char *)num_adrress, (xdrproc_t) xdr_wrapstring, symbolic);

    std::cout << *symbolic << std::endl;
    return 0;
}

我像这样运行服务器和客户端:

./server
./client 64.233.166.94
。服务器打印
208-107-167-85-dynamic.midco.net
这是我期待的结果,但是当服务器尝试返回时它会抛出分段错误。

c++ c++11 rpc
1个回答
0
投票

代码中存在一些反惯用的C++以及RPC API的错误使用。这是清理后的版本:

服务器:

#include <iostream>
#include <sys/socket.h>
#include <netdb.h>
#include <rpc/rpc.h>
#include <rpc/svc.h>
#include <rpc/xdr.h>

char *from_number_to_symbolic(char* number_arg) {

  int number = *reinterpret_cast<int*>(number_arg); // <- fixed API usage

  sockaddr_in temp = {AF_INET, SOCK_STREAM,
                      {static_cast<in_addr_t>(number)}, {}};
  static char symbolic[100];
  static char *symbolic_ret = symbolic;              // <- fixed API usage

  getnameinfo(reinterpret_cast<sockaddr*>(&temp), sizeof(sockaddr_in),
              symbolic, 100, nullptr, 0, 0);
  std::cout << std::endl << symbolic << std::endl;
  return reinterpret_cast<char*>(&symbolic_ret);     // <- fixed API usage
}

int main()
{
  registerrpc(42700, 1, 1, from_number_to_symbolic, 
              reinterpret_cast<xdrproc_t>(xdr_int), 
              reinterpret_cast<xdrproc_t>(xdr_wrapstring));
  svc_run();
  return 0;
}

客户:

#include <iostream>
#include <cstdlib>
#include <rpc/rpc.h>
#include <arpa/inet.h>
#include <netdb.h>

int from_numeric_to_int(char* numeric) {
  struct in_addr number;
  inet_pton(AF_INET, numeric, &number);

  return number.s_addr;
}

int main(int argc, char* argv[])
{
  if (argc != 2)
  {
      exit(1);
  }

  int int_adrress = from_numeric_to_int(argv[1]);
  char* symbolic = nullptr; // <- no need to allocate on the heap

  auto ret = callrpc("127.0.0.1", 42700, 1, 1, 
                     reinterpret_cast<xdrproc_t>(xdr_int), 
                     reinterpret_cast<char*>(&int_adrress), 
                     reinterpret_cast<xdrproc_t>(xdr_wrapstring), 
                     reinterpret_cast<char*>(&symbolic));
  clnt_perrno(static_cast<clnt_stat>(ret));

  std::cout << symbolic << std::endl;

  xdr_free(reinterpret_cast<xdrproc_t>(xdr_wrapstring), 
           &symbolic); // <-- memory leak fix

  return 0;
}
© www.soinside.com 2019 - 2024. All rights reserved.