首次使用GRPC遇值未传递问题:Stat返回值无法传递至Fetch
问题分析与解决
你的问题出在两个核心点上:
1. 指针参数传递逻辑错误
Stat函数里的void* file_status是传值参数,你在函数内给file_status赋值&response,只是修改了这个形参的副本,完全不会影响调用者(Fetch里的response变量)的实际地址。就像你把家门牌号告诉快递员,快递员自己在本子上改了个号,对你家的地址没有任何影响。
2. 局部变量生命周期问题
Stat里的dfs_service::File_Metadata response是局部变量,函数执行结束后这个变量会被销毁,内存会被回收。就算你之前把它的地址传出去,后续访问这个地址得到的都是无效的野指针值。
修正方案
直接将参数改为具体的dfs_service::File_Metadata*类型,通过GRPC消息的CopyFrom方法把数据复制到调用者的变量中,避免传递局部变量地址:
修正后的代码
StatusCode DFSClientNodeP1::Stat(const std::string &filename, dfs_service::File_Metadata* file_status) { StatusCode return_status; grpc::ClientContext context; dfs_service::File request; dfs_service::File_Metadata response; request.set_filename(this->WrapPath(filename)); // 必须检查gRPC调用的返回状态 grpc::Status status = this->service_stub->get_status(&context, request, &response); if (!status.ok()) { // 处理调用失败场景,比如返回错误码 return StatusCode::ERROR; } std::cout << "SHOULD BE " << response.filesize() << std::endl; // 将响应数据复制到调用者传入的对象中 file_status->CopyFrom(response); return return_status; } StatusCode DFSClientNodeP1::Fetch(const std::string &filename) { StatusCode return_status; dfs_service::File_Metadata response; return_status = Stat(filename, &response); std::cout << "WHAT IT IS " << response.filesize() << std::endl; return StatusCode::OK; }
额外说明
- 避免使用
void*无类型指针,直接用具体消息类型指针,既安全又无需强制类型转换,减少出错概率。 - 务必检查gRPC调用返回的
grpc::Status,否则调用失败时你无法感知,会继续处理空或错误的响应数据。 - GRPC消息对象支持复制操作,
CopyFrom能完整复制所有字段,调用者的response在Fetch内创建,生命周期覆盖整个调用流程,不存在内存无效问题。
内容的提问来源于stack exchange,提问作者Josh Voytek
相关产品推荐
相关产品推荐

