Managing Circular References
As described in Working with Shallow and Deep Copies, the HydraExpress handle-body implementation uses a simple reference count to decide when to destroy a body. This strategy is efficient and accurate for most classes. However, this strategy fails when a body contains a handle to itself.
For example, the class declaration below shows a handle class that may contain an instance of itself as a data member:
class EMailMessage : public rwsf::XmlBindingHandle {
// ...
setInResponseTo(const EMailMessage& message);
// ...
This declaration allows a class to contain itself, as shown in the sample below:
EMailMessage message;
message.setInResponseTo(message); //1 Error!
} //2
Line //1 copies the handle into the body, creating the object graph in Figure 4:
Figure 4 – Circular reference
Even though message goes out of scope on line //2, the body is never deleted. The destructor for message decrements the reference count on the body. However, the handle contained within the body still refers to the body, so the reference count on the body is not zero. Therefore, the destructor for message does not delete the body. Since no other handles exist, the program cannot replace the handle within the body. The result is a memory leak.
Note that this situation is a case where the data binding offers more flexibility than XML itself. Because the data binding uses the handle-body idiom, an element can logically contain a full copy of itself. An XML document cannot literally represent this structure. Each copy of the element would need to contain a full copy of the element, including a nested copy of the element. The nested copy of the element would also need to contain a copy of the element, including a nested copy. An XML document with this structure would require an infinite number of nested copies. For this reason, HydraExpress cannot serialize an element that contains itself either directly or indirectly.
An XML document typically represents self-containment by using a reference rather than a literal copy. For data structures that represent self-containment, we recommend rewriting the schema to allow a reference type as an alternative to containment.