There are two possible solutions to the problem: I don’t understand the c++ semantics or g++ does.
I am programming a simple network game now. I have been building a library the game uses to communicate over the network. There is a class designated to handle the connection between the apps. Another class implements server functionality so it possess a method accept(). The method is to return a Connection class.
There are a few way to return the class. I have tried these three:
Connection accept() {
...
return Connection(...);
}
Connection* accept() {
...
return new Connection(...);
}
Connection& accept() {
...
Connection *temp = new Connection(...);
return *temp;
}
All three were accepted by g++. The problem is that the third is somewhat faulty. When you use internal information of the object of type Connection, you will fail. I don’t know what is wrong because all fields within the object look like initiasized. My problem is that when I use any function from protocol buffers library my program is terminated by Segmentation fault. The function below fails every it calls the protobuf library.
Annoucement Connection::receive() throw(EmptySocket) {
if(raw_input->GetErrno() != 0) throw EmptySocket();
CodedInputStream coded_input(raw_input);
google::protobuf::uint32 n;
coded_input.ReadVarint32(&n);
char *b;
int m;
coded_input.GetDirectBufferPointer((const void**)&b, &m);
Annoucement ann;
ann.ParseFromArray(b, n);
coded_input.Skip(n);
return ann;
}
I get this every time:
Program received signal SIGSEGV,
Segmentation fault. 0x08062106 in
google::protobuf::io::FileInputStream::CopyingFileInputStream::GetErrno
(this=0x20) at
/usr/include/google/protobuf/io/zero_copy_stream_impl.h:104
When I changed the accept() to the second version, it finnaly worked (the first is good too but I modified conception in the meanwhile).
Have you come across any problem that is similiar to this one? Why the third version of accept() is wrong? How should I debug the program to find such a horrible bug (I thought protobuf need some fix whereas the problem was not there)?
First, returning by reference something allocated on the heap is a sure recipe for a memory leak so I would never suggest actually doing that.
The second case can still result in a leak unless the ownership semantics are very well specified. Have you considered using a smart pointer instead of a raw pointer?
As for why it doesn’t work, it probably has to do with ownership semantics and not because you’re returning by reference, but I can’t see a problem in the posted code.