我遇到了一个关于使用protobuf动态创建消息的奇怪问题。如下面的代码所示,它可以正常工作。但如果我以下列方式注释掉主要功能:
#if 0
const Descriptor* desc = pb.pool()->FindMessageTypeByName("SvrRegRsp");
DynamicMessageFactory factory;
const Message *message = factory.GetPrototype(desc);
Message *p_msg = message->New();
#endif
Message* p_msg = get_msg(&pb);
它核心!似乎主要的不同只是在函数中包装消息的创建。当我查询调用堆栈时:
(gdb) where
#0 0x0000000001436ed0 in ?? ()
#1 0x00007ff218c8f0e3 in google::protobuf::internal::ReflectionOps::Clear (message=0x1437aa0)
at google/protobuf/reflection_ops.cc:133
#2 0x00007ff218c3328b in InlineParseFromCodedStream (message=0x1437aa0, input=0x7ffc82fc3aa0)
at google/protobuf/message_lite.cc:131
#3 InlineParseFromArray (message=0x1437aa0, size=<optimized out>, data=<optimized out>)
at google/protobuf/message_lite.cc:143
#4 google::protobuf::MessageLite::ParseFromArray (this=0x1437aa0, data=<optimized out>,
size=<optimized out>) at google/protobuf/message_lite.cc:207
#5 0x000000000040137e in parse_msg (p_msg=0x1437aa0,
buf=0x7ffc82fc3dc0 "\b\237\215\006\022\024QT-SIM-504761089-101", len=26) at pb_test.cpp:46
#6 0x000000000040172d in main (argc=1, argv=0x7ffc82fc42c8) at pb_test.cpp:95
(gdb) fr 1
#1 0x00007ff218c8f0e3 in google::protobuf::internal::ReflectionOps::Clear (message=0x1437aa0)
at google/protobuf/reflection_ops.cc:133
133 reflection->ListFields(*message, &fields);
(gdb) p reflection->ListFields
Cannot take address of method ListFields.
似乎ListFields是Null(纯虚函数调用)。任何人都可以帮助我找出为什么会发生这种情况?为什么在将创建包装在函数中时代码不起作用。提前致谢!
在文件test.proto中:
message SvrRegRsp{
required int32 RetCode = 1;
required string SID = 2;
}
cpp文件:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <string>
#include <google/protobuf/descriptor.pb.h>
#include <google/protobuf/dynamic_message.h>
#include <google/protobuf/compiler/importer.h>
using namespace google::protobuf;
using namespace google::protobuf::compiler;
enum {
MAX_PACKET_LEN = 1024,
};
int gen_msg(Importer* pb, char* buf, int* len)
{
const Descriptor* desc = pb->pool()->FindMessageTypeByName("SvrRegRsp");
DynamicMessageFactory factory;
const Message *message = factory.GetPrototype(desc);
Message *p_msg = message->New();
const Reflection *reflection = p_msg->GetReflection();
const FieldDescriptor *field = desc->field(1);
reflection->SetString(p_msg, field, "QT-SIM-504761089-101");
field = desc->field(0);
reflection->SetInt32(p_msg, field, 99999);
p_msg->SerializeToArray(buf, *len) ;
*len = p_msg->ByteSize();
std::string s = p_msg->DebugString();
printf("req: %s\nsize: %d\n", s.c_str(), *len);
return 0;
}
int parse_msg(Message* p_msg, const char* buf, int len)
{
if(p_msg) {
p_msg->ParseFromArray(buf, len); // core here, because p_msg vptr is NULL.
std::string s = p_msg->DebugString();
printf("rsp2:\n%s\nsize: %d\n", s.c_str(), len);
}
return 0;
}
Message* get_msg(Importer* pb)
{
const Descriptor* desc = pb->pool()->FindMessageTypeByName("SvrRegRsp");
DynamicMessageFactory factory;
const Message *message = factory.GetPrototype(desc);
Message *p_msg = message->New();
return p_msg;
}
int main(int argc, char** argv)
{
char cwd[256] = {0};
getcwd(cwd, sizeof(cwd));
printf("cwd: %s\n", cwd);
DiskSourceTree disk;
disk.MapPath("", cwd);
Importer pb(&disk, NULL);
const FileDescriptor* file_desc = pb.Import("test.proto");
if(!file_desc) {
return -1;
}
char packet[MAX_PACKET_LEN] = {0};
int len = MAX_PACKET_LEN;
gen_msg(&pb, packet, &len);
//#if 0
const Descriptor* desc = pb.pool()->FindMessageTypeByName("SvrRegRsp");
DynamicMessageFactory factory;
const Message *message = factory.GetPrototype(desc);
Message *p_msg = message->New();
//#endif
// Message* p_msg = get_msg(&pb);
parse_msg(p_msg, packet, len);
return 0;
}
答案 0 :(得分:0)
检查生成的factory.GetPrototype(desc);
和message->New();
代码
如果他们保留指针并且在返回呼叫者时不释放,则
然后当工厂超出范围时,它们就会被破坏而你正在访问悬空指针。