You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

调用RPC函数返回时触发Segmentation Fault问题求助

RPC返回时触发段错误问题

客户端调用RPC函数传入整数参数,服务端将其转换为符号地址,服务端能成功转换并打印结果,但返回时触发Segmentation Fault(段错误)。

服务端代码

#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,但返回时触发段错误。


问题原因与修复

1. 核心问题点

  • 服务端函数签名不匹配:from_number_to_symbolic期望接收int参数,但注册RPC时被强制转换为char* (*)(char*),RPC框架会按错误的签名传递参数,导致内存访问越界。
  • 客户端参数传递错误:callrpc传入的是原始字符串指针,而非转换后的整数指针,导致服务端解析到错误的数据。
  • 服务端sockaddr_in初始化错误:错误将sin_port赋值为SOCK_STREAM,不符合地址结构规范。

修复后的服务端代码

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

char *from_number_to_symbolic(char *arg) {
    // 从RPC序列化数据中解析出int参数
    int number;
    XDR xdrs;
    xdrmem_create(&xdrs, arg, sizeof(int), XDR_DECODE);
    if (!xdr_int(&xdrs, &number)) {
        return strdup("Invalid parameter");
    }
    xdr_destroy(&xdrs);

    // 正确初始化sockaddr_in结构
    struct sockaddr_in temp;
    memset(&temp, 0, sizeof(temp));
    temp.sin_family = AF_INET;
    temp.sin_addr.s_addr = number;

    static char symbolic[100]; 
    getnameinfo((struct sockaddr *) &temp, sizeof(struct sockaddr_in), symbolic, sizeof(symbolic), 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);
    }

    int *int_address = new int;
    *int_address = from_numeric_to_int(argv[1]);
    char **symbolic = new char*;
   
    // 传入转换后的整数指针
    callrpc("127.0.0.1", 42700, 1, 1, (xdrproc_t)xdr_int, (char *)int_address, (xdrproc_t)xdr_wrapstring, symbolic);

    std::cout << *symbolic << std::endl;
    // 释放RPC分配的内存
    xdr_free((xdrproc_t)xdr_wrapstring, (char*)*symbolic);
    delete int_address;
    delete symbolic;
    return 0;
}

额外说明

  • 客户端需调用xdr_free释放RPC框架分配的字符串内存,避免内存泄漏。
  • 服务端使用static char存储返回值是安全的,因为RPC框架会在返回前完成数据序列化。

内容的提问来源于stack exchange,提问作者Tomislav Farkaš

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.02 15:16:00