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

使用Protobuf在C++17中序列化时出现段错误:消息作为字段引发的问题

Protobuf在C++17中序列化时出现段错误:消息作为字段引发的问题

之前我碰到过一个类似的Protobuf序列化报错问题,但这次我把问题精准定位后,还是决定单独来梳理下。我的需求很明确:用Protobuf在C++17环境下完成数据序列化,但过程中触发了段错误,而且我已经把问题范围缩小到消息作为字段这个场景上了。

我在./proto目录下的proto文件内容大概是这样的:

syntax = "proto3";
package my_proto;

// 定义内部消息
message DetailInfo {
  int32 code = 1;
  string content = 2;
}

// 外部消息,把内部消息作为字段
message MainData {
  DetailInfo detail = 1;
  repeated string tags = 2;
}

最开始我写的C++代码大概是这样的,结果一运行就段错误:

#include <iostream>
#include "proto/main_data.pb.h"

int main() {
  GOOGLE_PROTOBUF_VERIFY_VERSION;
  
  MainData data;
  // 错误写法:直接访问detail字段的成员
  data.detail().set_code(404);
  data.detail().set_content("not found");
  
  std::string out_str;
  data.SerializeToString(&out_str);  // 这里触发段错误
  
  google::protobuf::ShutdownProtobufLibrary();
  return 0;
}

后来我折腾了好一阵子才搞明白问题出在哪!原来Protobuf的嵌套消息字段,默认是处于未初始化的状态,直接通过data.detail()获取的是const引用,根本不能用来修改成员,而且底层对象可能还没分配内存,直接访问自然就踩内存了。

正确的做法应该是用Protobuf提供的mutable_<字段名>()方法,先获取可修改的消息指针,确保对象被正确初始化:

#include <iostream>
#include "proto/main_data.pb.h"

int main() {
  GOOGLE_PROTOBUF_VERIFY_VERSION;
  
  MainData data;
  // 正确:用mutable_detail()获取可修改的指针
  data.mutable_detail()->set_code(200);
  data.mutable_detail()->set_content("success");
  
  // 如果是repeated类型的消息字段,要用add_<字段名>()来添加新元素
  data.add_tags("protobuf");
  data.add_tags("c++17");
  
  std::string out_str;
  if (data.SerializeToString(&out_str)) {
    std::cout << "序列化成功,长度:" << out_str.size() << std::endl;
  } else {
    std::cerr << "序列化失败!" << std::endl;
  }
  
  google::protobuf::ShutdownProtobufLibrary();
  return 0;
}

另外还要注意,如果是用set_allocated_<字段名>()手动分配内存的情况,一定要记得不要重复释放,Protobuf在销毁外层消息时会自动释放内部分配的消息对象,所以手动分配后别自己再delete了,不然会触发双重释放的错误。

总结下来,这种段错误本质上就是没搞懂Protobuf C++接口的内存管理逻辑,误用了const引用或者访问了未初始化的嵌套消息对象,只要跟着官方接口的规范来,用对mutable系列方法,基本就能避开这个坑。

备注:内容来源于stack exchange,提问作者Daniil Yefimov

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.13 16:54:40