2011-07-10 11 views
7

Para un proyecto escolar, tenemos que enviar archivos grandes a través de la red. Debemos utilizar Poco :: XML para nuestros datos.¿Cómo resuelvo las pérdidas de memoria que se informa que residen en la cadena STL?

Después de que nuestros archivos se envían a través de la red, parece que la memoria no se libera.

Aquí se muestra un ejemplo de un archivo de ~9 Mb en la pieza de alojamiento:

valgrind --leak-check=full --show-reachable=yes -v ourExecutable parms devuelve:

12,880,736 bytes in 37 blocks are definitely lost in loss record 101 of 101 
    at 0x4C2747E: operator new(unsigned long) (vg_replace_malloc.c:261) 
    by 0x5A3AC88: std::string::_Rep::_S_create(unsigned long, unsigned long, std::allocator<char> const&) (in /usr/lib64/gcc/x86_64-pc-linux-gnu/4.4.4/libstdc++.so.6.0.13) 
    by 0x5A3BC4A: std::string::_Rep::_M_clone(std::allocator<char> const&, unsigned long) (in /usr/lib64/gcc/x86_64-pc-linux-gnu/4.4.4/libstdc++.so.6.0.13) 
    by 0x5A3C1BB: std::string::reserve(unsigned long) (in /usr/lib64/gcc/x86_64-pc-linux-gnu/4.4.4/libstdc++.so.6.0.13) 
    by 0x5A3C68E: std::string::append(std::string const&) (in /usr/lib64/gcc/x86_64-pc-linux-gnu/4.4.4/libstdc++.so.6.0.13) 
    by 0x5202359: Poco::XML::Element::innerText() const (in /home/tomwij/IGS/trunk/Project/external/lib/libPocoXML.so.8) 
    by 0x4145BF: NodeProtocol::getChildNodeStrValue(Poco::XML::Element*, std::string) (NodeProtocol.cpp:82) 
    by 0x41544F: NodeProtocol::deserialize(std::string const&) (NodeProtocol.cpp:200) 
    by 0x40B088: Node::handleClientPacket(PriorityElement*) (Node.cpp:760) 
    by 0x40A04C: Node::handlePackets() (Node.cpp:574) 
    by 0x4078EA: Node::run() (Node.cpp:162) 
    by 0x40772D: Node::activate() (Node.cpp:138) 

LEAK SUMMARY: 
    definitely lost: 12,888,036 bytes in 190 blocks 
    indirectly lost: 644,979 bytes in 1,355 blocks 
     possibly lost: 10,089 bytes in 27 blocks 
    still reachable: 306,020 bytes in 43 blocks 
     suppressed: 0 bytes in 0 blocks 

La función que está justo antes de Poco es

const string NodeProtocol::getChildNodeStrValue(Element * elem, string child) 
{ 
    Element* tempNode = elem->getChildElement(child); 
    XMLString result(tempNode->innerText()); 
    string ret = string(fromXMLString(result)); 
    result.clear(); 
    return ret; 
} 

que exige

XMLString Element::innerText() const 
{ 
    XMLString result; 
    Node* pChild = firstChild(); 
    while (pChild) 
    { 
     result.append(pChild->innerText()); 
     pChild = pChild->nextSibling(); 
    } 
    return result; 
} 

(Tenga en cuenta que es XMLStringstd::string)

memoria ¿Por qué el append de cadena STL una fuga?

Si acabo de asignar en lugar de utilizar los constructores de copia da el mismo problema.


EDIT:

estoy usando la última estable GNU GCC 4.4.4 en Gentoo x64 (Linux-2.6.34-gentoo-r12).

Más funciones de la pila de llamadas (despojados grandes trozos irrelevantes de código/IF estructuras):

Command * NodeProtocol::deserialize(const string & msg) 
{ 
    DOMParser xmlParser; 

    // Get the root node. 
    AutoPtr<Document> doc = xmlParser.parseString(msg); 
    AutoPtr<Element> rootElement = doc->documentElement(); 

    string root = fromXMLString(rootElement->nodeName()); 
    string name = getChildNodeStrValue(rootElement, "name"); 
    string data = getChildNodeStrValue(rootElement, "data"); 
    return new PutCommand(name, data); 
} 

y

void Node::handleClientPacket(PriorityElement * prio) 
{ 
     Command * command = NodeProtocol::deserialize(prio->fPacket); 

     // CUT: Access some properties of command, let the command execute. 

     delete command; 
} 

y

void Node::handlePackets() 
{ 
    PriorityElement * prio = fQueue->top(); 
    fQueue->pop(); 

    if (prio->fSource == kCLIENT) 
     handleClientPacket(prio); 
    else if (prio->fSource == kNODE) 
     handleNodePacket(prio); 

    delete prio; 
} 

donde fQueue es:

priority_queue< PriorityElement*, vector<PriorityElement*>, ComparisonFunction > 
+2

No mostró el código de la función 'OurExecutable :: handleClientPacket', ni ninguna de las anteriores en la pila de llamadas. Ninguna de las funciones cuyo código ha publicado muestra ninguna asignación dinámica. Entonces la fuga no puede estar allí. –

+0

¿Realiza usted mismo alguna asignación de memoria dinámica? – Marlon

+0

¿Qué compilador se usa (y su versión)? ¿Qué implementación de biblioteca estándar se usa? –

Respuesta

9

Haría este comentario, pero aparentemente no tengo el representante. ¿Has recordado hacer que el destructor para Command sea virtual? Si name o data son campos de PutCommand en lugar de Command y la Command destructor no es virtual, no pueden ser liberados adecuadamente cuando se elimina command en handleClientPacket.

+0

Me alegro de que no hayas hecho este comentario. Aparentemente, el problema real parecía estar muy lejos de la fuente ...:/ –

+0

** Lección aprendida: ** No necesariamente mira la fuente, también ve dónde se almacena y qué sucede con ella. –

Cuestiones relacionadas