I have a simple Client/Server that is using Protobuf to send messages back and forth. I am trying to use a Union that has a message with unions of possible message types int it. See the proto file below.
import "Heartbeat.proto";
message PBMessage
{
optional Heartbeat heartbeat = 1;
optional HeartbeatAck heartbeatAck = 2;
}
The heartbeat.proto contains the definition of those other messages.
I attempt to add a heartbeat to the message and send that to the server. The server actually receives this message fine but it appears that the client is performing a cleanup when the function returns and then excepts. I believe this has to do with the set_allocated_heartbeat function call. I have attempted to make the heartbeat structure itself a member of the class but that changed nothing.
Here is the client code to send the hearbeat message.
void MyClass::sendHeartBeat(void)
{
HsmHeartbeat heartbeat;
unsigned char buffer[1024];
heartbeat.set_sequenceid(m_currentHBSequence++);
m_Message.set_allocated_heartbeat(&heartbeat);
if(heartbeat.IsInitialized() && m_Message.IsInitialized())
{
google::protobuf::io::ArrayOutputStream arr(buffer, sizeof(buffer));
google::protobuf::io::CodedOutputStream output(&arr);
m_Message.SerializeToCodedStream(&output);
sendto(m_ClientSocket, (char*) buffer, output.ByteCount(), 0, (sockaddr *) &m_ClientSendSocket, sizeof(m_ClientSendSocket));
}
}
Here is the stack trace:
*** glibc detected *** ./client: free(): invalid pointer: 0xbfd882e0 ***
======= Backtrace: =========
/lib/i386-linux-gnu/libc.so.6(+0x73e42)[0xb74d2e42]
/usr/lib/i386-linux-gnu/libstdc++.so.6(_ZdlPv+0x1f)[0xb76f851f]
./client[0x804a7a2]
./client[0x804da00]
./client[0x804d7a3]
./client[0x804db01]
/lib/i386-linux-gnu/libc.so.6(__libc_start_main+0xf3)[0xb74784d3]
./client[0x804a179]
EDIT: Clarification, m_Message is a PBMessage.
The set_allocated_
methods take ownership of the parameter. You should never pass in a stack-allocated object, only a heap-allocated one. The parent message will take care of deleting that object later on. (Relying on calling release_
later on to prevent deletion is fragile; I'd recommend against it.)
For your node, I'd suggest instead that you simply use mutable_heartbeat()
to get an instance of the sub-object. Note that since you're reusing the parent message ( m_Message
), the inner message will be reused too -- when m_Message
is cleared, it places all its children in a freelist to be reused later. So, using mutable_heartbeat()
will only allocate memory the first time, if that's what you're worried about.
PS. instead of setting up ArrayOutputStream
and CodedOutputStream
, do this:
int size = m_Message.ByteSize();
assert(size < sizeof(buffer));
m_Message.SerializeWithCachedSizesToArray(buffer);
It'll be faster.
Solution:
Add m_Message.release_heartbeat() prior to exiting the function.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.