2011-05-17 11 views
7

tengo esta claseC++ pérdida de memoria cuando se utiliza std :: string en la matriz de memoria compartida

class LayoutEntry 
{ 
    unsigned int id_; 
    string name_; 
    bool isInput_; 
}; 

El constructor de copia se ve así:

LayoutEntry(const LayoutEntry &other) 
     : id_(other.id_), 
     name_(other.name_), 
     isInput_(other.isInput_) 
    { 
    } 

objetos de esta clase se ponen dentro de un mapa dentro de otra clase

class DataLayoutDescription 
{ 
    unsigned int sz_; 
    set<LayoutEntry, SortByOffset> impl; 

    // HERE!!! 
    map<unsigned int, LayoutEntry> mapById; 

El constructor de copia de esta clase tiene el siguiente aspecto:

DataLayoutDescription::DataLayoutDescription(const DataLayoutDescription &other) 
    :sz_(other.sz_), impl(other.impl), mapById(other.mapById) 
{ 
} 

Ahora la pregunta:

  • I Get una pérdida de memoria para cada LayoutEntry cuando se ejecuta como impreso
  • Si quito mapById(other.mapById) en el constructor copia de DataLayoutDescription entonces no hay memleak
  • Si elimino name_(other.name_), Las pérdidas de memoria también se han ido

¿Por qué?

EDITAR

Para la prueba I impulsar el uso :: unittest al final consigo un vertedero de pérdida de memoria

C:\wc\05_EAPGit\Debug>EapLibTest.exe --run-test=SharedVectorTest 
Running 7 test cases... 

*** No errors detected 
Detected memory leaks! 
Dumping objects -> 
{1378} normal block at 0x005815C0, 16 bytes long. 
Data: <    > CD CD CD CD CD CD CD CD CD CD CD CD CD CD CD CD 
{1377} normal block at 0x00581580, 16 bytes long. 
Data: <    > CD CD CD CD CD CD CD CD CD CD CD CD CD CD CD CD 
{1376} normal block at 0x00581540, 16 bytes long. 
Data: <    > CD CD CD CD CD CD CD CD CD CD CD CD CD CD CD CD 
Object dump complete. 

Razón Posible? que persisten la DataLayoutDescription en un área de memoria compartida utilizando este método

void DataLayoutDescription::Save(LayoutEntry *les, unsigned int maxEntries) const 
{ 
    int n = std::max(impl.size(), maxEntries); 
    int i = 0; 
    for (DataLayoutDescription::iterator it = begin(); it != end(); ++it) 
    { 
     les[i] = *it; // Source of memory leak here??? 
     ++i; 
    } 
} 

que eliminar la referencia de la tienda hormiga iterador una copia de esta en la matriz que se encuentra en la región de memoria compartida. ¿Hay algo mal? La memoria compartida se elimina al salir.

furhter Trackdown El LayoutEntry clase se coloca en una matriz dentro de un área de memoria compartida y contiene una cadena. El motivo de la pérdida de memoria es que la cadena se redimensiona. Por lo tanto, asigna más memoria en el montón. Ahora supongo que esta memoria no se liberará ya que la memoria original se encuentra en la memoria compartida. Podría ser ésta la razón? Lo siguiente que intentaré es eliminar la cadena y reemplazarla por una matriz de caracteres de longitud fija.

... después de varios minutos

Ésta era la misma. Después de reemplazar la cadena con una matriz fija de char, la pérdida de memoria desapareció. Espero que esto ayude a alguien.

+3

Esto se ve perfecto. ¿Qué te hace pensar que hay pérdida de memoria aquí? –

+6

No hay fuga de memoria aparente en el código que ha publicado. ¿Por qué crees que tienes uno? –

+0

Agregué el volcado – schoetbi

Respuesta

2

El motivo de la fuga fue la clase LayoutEntry que almacena una cadena. El objeto base (antes de la modificación) se colocó en una matriz dentro de un área de memoria compartida. Después de alterar la cadena, se realizó una operación de cambio de tamaño, esta memoria se perdió. Después de reemplazar la cadena por una matriz de caracteres (longitud fija), la fuga de memoria desapareció. Estoy contento ahora, pero me pregunto si la clase de cadena hace algo mal, ¿o hay alguna manera de poner un asignador personalizado en std :: string? No lo necesitaré porque iré con la matriz de caracteres, pero tengo curiosidad de saber si algo así funcionaría y si estoy de acuerdo con estas suposiciones.

Esta es la clase modificada

class LayoutEntry 
{ 
    unsigned int id_; 
    char name_[128]; 
    bool isInput_; 
}; 

Gracias a todos por su ayuda! Los consejos para depurar la fuga de memoria me ayudaron mucho.

+2

La cadena C++ asigna más memoria para contener la cadena real. Lo que copiaste en la memoria compartida era solo un puntero y una longitud. La cadena real nunca estuvo en la memoria compartida, por lo tanto, cuando elimina la memoria compartida, pierde el puntero al que se habría llamado eliminar []. –

3

Suponiendo que cuando dices que tienes una pérdida de memoria, te refieres a un verificador como Purify o que valgrind te lo dice, el escenario más probable es que de algún modo estés goteando LayoutEntry objetos, NO string objetos directamente. Fui mordido por esta vez y me confundí porque mi propio objeto se estaba filtrando, pero la fuga fue etiquetada (por valgrind) a std::string, lo que hizo que fuera más difícil de encontrar.

O bien, puede estar detectando un crecimiento.¿Intentó hacer un clear en su mapa antes de salir?

4

Parece the memory leak that was introduced in Visual Studio 2010 C++ standard library, fixed with SP1. Si es tu compilador (sin SP1) ese es ciertamente el problema.

Ver también esas respuestas: STL container leak

+0

Acepté esto no porque sea la respuesta más fácil para mí pero los síntomas lucen así. No he hecho todo lo que sugirió, pero dado que goteo también 16 bytes, parece que sí. Una cosa que todavía me molesta es que tengo SP1 instalado. – schoetbi

+0

Si tiene VS2010 SP1 instalado, siga mi respuesta aceptada en el enlace (ni siquiera remarcó que era de mi parte ...). – Klaim

1

Si tiene números de asignación consistentes en las fugas, se puede establecer el asignador de memoria de depuración a romperse en que la asignación específica utilizando _CrtSetBreakAlloc.

http://msdn.microsoft.com/en-us/library/4wth1ha5.aspx

Por ejemplo, la adición de _CrtSetBreakAlloc(1378) a su código provocará una interrupción de depuración en la asignación de número de bloque 1378. A continuación, puede utilizar el depurador para seguir el código de nuevo a la persona que llama.

Cuestiones relacionadas