我有一个通过
protoc
从 proto
文件生成的代码。创建 protobuf 对象并序列化到 string
后,当函数结束时,在创建的 proto
对象中调用析构函数,此时我收到错误,导致内部 desctructo 形式不可编辑生成的代码。
CORRUPT HEAP: Bad head at 0x3fcf7090. Expected 0xabba1234 got 0x313a3446
assert failed: multi_heap_free multi_heap_poisoning.c:253 (head != NULL)
Backtrace: 0x403760ca:0x3fcf6d50 0x40380d39:0x3fcf6d70 0x403886dd:0x3fcf6d90 0x4038784f:0x3fcf6eb0 0x40376662:0x3fcf6ed0 0x4038870d:0x3fcf6ef0 0x4220c769:0x3fcf6f10 0x42052fed:0x3fcf6f30 0x42047af1:0x3fcf6f50 0x42047f02:0x3fcf6f70 0x4203b61a:0x3fcf7000 0x4201fa93:0x3fcf7130 0x4201fdcd:0x3fcf71b0 0x42009ff5:0x3fcf7280 0x4225b0d0:0x3fcf7350 0x40384751:0x3fcf7370
0x403760ca: panic_abort at /home/x/esp/esp-idf/components/esp_system/panic.c:402
0x40380d39: esp_system_abort at /home/x/esp/esp-idf/components/esp_system/esp_system.c:128
0x403886dd: __assert_func at /home/x/esp/esp-idf/components/newlib/assert.c:85
0x4038784f: multi_heap_free at /home/x/esp/esp-idf/components/heap/multi_heap_poisoning.c:253 (discriminator 1)
0x40376662: heap_caps_free at /home/x/esp/esp-idf/components/heap/heap_caps.c:361
0x4038870d: free at /home/x/esp/esp-idf/components/newlib/heap.c:39
0x4220c769: operator delete(void*) at /builds/idf/crosstool-NG/.build/xtensa-esp32s3-elf/src/gcc/libstdc++-v3/libsupc++/del_op.cc:49
0x42052fed: StructureReport::~StructureReport() at /home/x/y/Project/x-x/x-x-x/components/protobufParser/protobuf-c/structure.pb.cc:147
0x42047af1: GatewayReport::clear_report() at /home/x/y/Project/x-x/x-x-x/components/protobufParser/protobuf-c/reports.pb.cc:1150 (discriminator 1)
0x42047f02: GatewayReport::SharedDtor() at /home/x/y/Project/x-x/x-x-x/components/protobufParser/protobuf-c/reports.pb.cc:1113
(inlined by) GatewayReport::~GatewayReport() at /home/x/y/Project/x-x/x-x-x/components/protobufParser/protobuf-c/reports.pb.cc:1105
原型文件是。
message GatewayReport {
string mac = 1;
oneof report {
DeviceReport device = 3;
StructureReport structure = 7;
}
}
message StructureReport {
string mac = 1;
string type = 2;
string revision = 3;
repeated StructureNode nodes = 4;
}
message StructureNode {
bytes uuid = 1;
repeated string capabilities = 2;
}
简单的代码:
std::string ProtobufParser::parseGatewayReportMsg()
{
std::string parsedMsg;
StructureReport structureRep;
GatewayReport gatewayReport;
structureRep.set_mac("FF:FF:FF:FF:FF:FF");
structureRep.set_type("type");
structureRep.set_revision("rev");
auto node = structureRep.add_nodes();
node->add_capabilities("cap");
node->set_uuid("uuid");
gatewayReport.set_mac(deviceProperties->GetMac());
gatewayReport.set_allocated_structure(&structureRep);
gatewayReport.SerializeToString(&parsedMsg);
google::protobuf::ShutdownProtobufLibrary();
return parsedMsg;
}
值得一提的是,我的项目中有一个地方,protoc 对象已经创建,并且没有被破坏,并且所有工作都有效。所以这也证明了生成代码中析构函数中有些不正确。 要生成协议代码,我必须使用工具
protoc-3.15.1-linux-x86_64
。版本很重要,因为我拥有的 idf 库 google-protoc 需要这个版本才能正确工作。
您正在使用
set_allocated_structure(&structureRep)
,它获取指向对象的所有权,但该对象是一个局部变量,当函数退出时会被释放。相反,尝试声明并传递指针:
std::string ProtobufParser::parseGatewayReportMsg()
{
std::string parsedMsg;
StructureReport *structureRep = new StructureReport;
structureRep->set_mac("FF:FF:FF:FF:FF:FF");
structureRep->set_type("type");
structureRep->set_revision("rev");
auto node = structureRep->add_nodes();
node->add_capabilities("cap");
node->set_uuid("uuid");
gatewayReport.set_mac(deviceProperties->GetMac());
gatewayReport.set_allocated_structure(structureRep);
gatewayReport.SerializeToString(&parsedMsg);
google::protobuf::ShutdownProtobufLibrary();
return parsedMsg;
}