/// <summary> /// Resets a given pointer to the memory address /// of a newly created object (never assigned before). /// </summary> /// <param name="pointerAddr">The address of the pointer object.</param> /// <param name="newPointedAddr">The new pointed memory address.</param> /// <param name="allowDtion"> /// Whether the pointed object should have its destructor invoked just /// in case it is to be collected. The destruction must not be allowed /// when the object construction has failed due to a thrown exception. /// </param> void MemoryDigraph::ResetPointer(void *pointerAddr, void *newPointedAddr, bool allowDtion) { auto &sptrObjHashTableElem = m_sptrObjects.Lookup(pointerAddr); UnmakeReference(sptrObjHashTableElem, allowDtion); if (newPointedAddr != nullptr) MakeReference(sptrObjHashTableElem, newPointedAddr); }
/// <summary> /// Adds a new pointer to the graph. /// </summary> /// <param name="pointerAddr">The address of the pointer object.</param> /// <param name="pointedAddr">The memory address referred by the pointer.</param> void MemoryDigraph::AddPointer(void *pointerAddr, void *pointedAddr) { /* The edge origin is always a pointer. If the pointer is not a root vertex, find the container vertex, which is a piece of memory containing the pointer, so the connection to the pointed memory address will be set using the container rather than the pointer: */ auto containerMemBlock = m_vertices.GetContainerVertex(pointerAddr); // null if root auto &sptrObjHashTableElem = m_sptrObjects.Insert(pointerAddr, nullptr, containerMemBlock); if (pointedAddr != nullptr) MakeReference(sptrObjHashTableElem, pointedAddr); }
/// <summary> /// Sets the connection between a pointer and its referred memory address, /// creating an edge in the graph. /// </summary> /// <param name="sptrObjHashTableElem"> /// A hashtable element which represents the pointer. /// </param> /// <param name="pointedAddr">The referred memory address.</param> void MemoryDigraph::MakeReference( AddressesHashTable::Element &sptrObjHashTableElem, void *pointedAddr) { auto pointedMemBlock = m_vertices.GetVertex(pointedAddr); /* By the time the connection is to be set, the vertex representing the pointed memory block must already exist in the graph. If not present, that means it has been unappropriately collected too soon, or the vertex has been removed from the graph too early... */ _ASSERTE(pointedMemBlock != nullptr); MakeReference(sptrObjHashTableElem, pointedMemBlock); }
/// <summary> /// Adds a new pointer (constructed as a copy) to the graph. /// </summary> /// <param name="leftPointerAddr">The address of the pointer object to add.</param> /// <param name="rightPointerAddr">The address of the pointer object being copied.</param> void MemoryDigraph::AddPointerOnCopy(void *leftPointerAddr, void *rightPointerAddr) { /* The edge origin is always a pointer. If the pointer is not a root vertex, find the container vertex, which is a piece of memory containing the pointer, so the connection to the pointed memory address will be set using the container rather than the pointer: */ auto containerMemBlock = m_vertices.GetContainerVertex(leftPointerAddr); // null if root auto &leftSptrObjHTabElem = m_sptrObjects.Insert(leftPointerAddr, nullptr, containerMemBlock); auto &rightSptrObjHTabElem = m_sptrObjects.Lookup(rightPointerAddr); auto receivingVtx = rightSptrObjHTabElem.GetPointedMemBlock(); if (receivingVtx != nullptr) MakeReference(leftSptrObjHTabElem, receivingVtx); }
/// <summary> /// Resets a given pointer to the memory address /// of an object previously assigned to another pointer. /// </summary> /// <param name="pointerAddr">The address of the pointer object.</param> /// <param name="otherPointerAddr">The address of the other pointer object.</param> void MemoryDigraph::ResetPointer(void *pointerAddr, void *otherPointerAddr) { auto &leftSptrObjHashTabElem = m_sptrObjects.Lookup(pointerAddr); auto &rightSptrObjHashTabElem = m_sptrObjects.Lookup(otherPointerAddr); /* The reason this overload exists is that, differently from the other implementation of ResetPointer, where the vertex of the newly pointed address must be searched in the graph, here we can get this vertex cached with the sptr in the hash table. This allows the retrieval of vertices which no longer exists in the graph due to a previous collection, which despite not being the most common scenario, it is still possible. */ auto newlyPointedMemBlock = rightSptrObjHashTabElem.GetPointedMemBlock(); UnmakeReference(leftSptrObjHashTabElem, true); if (newlyPointedMemBlock != nullptr) MakeReference(leftSptrObjHashTabElem, newlyPointedMemBlock); }
extern "C" GLVREF GetWidgetsTestView() { return MakeReference(top); }