Pregunta

Por lo tanto, necesito un poco de ayuda.Estoy trabajando en un proyecto en C++.Sin embargo, creo que de alguna manera han logrado corromper mi montón.Esto se basa en el hecho de que he añadido un std::string a una clase y la asignación de un valor de otro std::string:

std::string hello = "Hello, world.\n";
/* exampleString = "Hello, world.\n" would work fine. */
exampleString = hello;

se bloquea en mi sistema con un volcado de pila.Así que, básicamente necesito parada y de ir a través de todo mi código y la gestión de la memoria cosas y averiguar donde me has jodido.El código base es todavía pequeño (alrededor de 1000 líneas), lo que es fácilmente capaz de hacer -.

Aún así, yo estoy por encima de mi cabeza con este tipo de cosas, así que pensé en tirar por ahí.Yo estoy en un sistema Linux y han hurgó con valgrind, y mientras no saber completamente lo que estoy haciendo, informe que el std::string's destructor fue un inválido libre.Tengo que admitir que al llegar el término "daños en el Montón' de una búsqueda en Google;cualquier propósito general de artículos sobre este tipo de cosas se agradece también.

(Antes de rm -rf ProjectDir, hacer de nuevo en C# :D)

EDITAR:No he dejado claro, pero de lo que estoy pidiendo son las formas en que un consejo de diagnosticar este tipo de problemas de memoria.Sé el std::string cosas que es correcto, así que es algo que he hecho (o un error, pero No hay Un Problema Con Seleccionar).Estoy seguro de que podría comprobar el código que he escrito y muy inteligente a la gente iba a ver el problema en ningún momento, pero quiero añadir que este tipo de análisis de código para mi "caja de herramientas", como lo había hecho.

¿Fue útil?

Solución

Estos son relativamente baratos mecanismos de para tener la posibilidad de resolver el problema:

  1. Mantenga un ojo en mi el montón de la cuestión de la corrupción - Estoy actualizando con las respuestas contundentes.El primero fue el equilibrio de new[] y delete[], pero ustedes ya están haciendo.
  2. Dar valgrind más de un go;es una excelente herramienta, y yo sólo deseo estaba disponible en Windows.Yo sólo retrasa su programa por la mitad, que es bastante bueno en comparación con el Windows equivalentes.
  3. Pensar en el uso de la Google Herramientas De Rendimiento como un reemplazo malloc/nuevo.
  4. ¿Has limpiado todos sus archivos objeto y volvió a empezar?Tal vez tu archivo..."subóptima"
  5. No estás assert()ing suficiente en el código.¿Cómo puedo saber que sin haberlo visto?Como el uso de hilo dental, nadie assert()s lo suficiente en su código.Agregar en una función de validación de los objetos y de la llamada que en el método de inicio y método de final.
  6. Son ustedes la compilación de la pared?Si no, hacerlo.
  7. Encuentra una pelusa como herramienta de PC-Lint.Una aplicación pequeña como la suya podría encajar en el PC-lint demo la página, es decir, no de compra para usted!
  8. Compruebe usted está Anular a cabo los punteros después de deleteing ellos.A nadie le gusta un colgando puntero.Mismo concierto con declarado pero sin asignar punteros.
  9. Deje de usar matrices.El uso de un vector en su lugar.
  10. No usar raw punteros.El uso de un puntero inteligente.No uso auto_ptr!Que cosa es...sorprendente;su semántica son muy extraña.En su lugar, elija una de las Impulso de punteros inteligentes, o algo fuera de la biblioteca Loki.

Otros consejos

Una vez había un bug que eludió a todos los regulares técnicas, valgrind, purificar etc.El bloqueo sólo sucedía en las máquinas con un montón de memoria y sólo en grandes conjuntos de datos de entrada.

Eventualmente, podemos relacionarlo utilizando el depurador de puntos de observación.Voy a intentar describir el procedimiento aquí:

1) Encontrar la causa de la falla.Parece que a partir de su código de ejemplo, que la memoria para "exampleString" se corrompe, y así no se puede escribir.Vamos a continuar con esta suposición.

2) Establecer un punto de interrupción en la última ubicación conocida de que "exampleString" es modificado o usado sin ningún problema.

3) Añadir un punto de inspección a los datos miembro de 'exampleString'.Con mi versión de g++, la cadena se almacena en _M_dataplus._M_p.Queremos saber cuando este miembro de datos los cambios.El GDB técnica para esto es:

(gdb) p &exampleString._M_dataplus._M_p
$3 = (char **) 0xbfccc2d8
(gdb)  watch *$3
Hardware watchpoint 1: *$3

Estoy, obviamente, el uso de linux con g++ y gdb aquí, pero creo que la memoria de reloj de puntos están disponibles con la mayoría de los depuradores.

4) Continuar hasta el punto de inspección se activa:

Continuing.
Hardware watchpoint 2: *$3

Old value = 0xb7ec2604 ""
New value = 0x804a014 ""
0xb7e70a1c in std::string::_M_mutate () from /usr/lib/libstdc++.so.6
(gdb) where

El gdb where comando le dará un seguimiento posterior de mostrar lo que dio lugar a la modificación.Esto es perfectamente legal la modificación, en cuyo caso sólo tienes que seguir - o, si tienes suerte será la modificación debido a la corrupción de memoria.En el último caso, usted debería ser capaz de revisar el código que se realmente causando el problema y esperamos solucionarlo.

La causa de nuestro error fue de un acceso a un array con un índice negativo.El índice fue el resultado de una conversión de un puntero a un 'int' modulos el tamaño de la matriz.El error se perdió por valgrind et al.como las direcciones de memoria asignadas cuando se ejecuta bajo estas herramientas nunca fue "> MAX_INT"y así nunca se tradujo en un índice negativo.

Oh, si usted quiere saber cómo depurar el problema, eso es simple.En primer lugar, conseguir un pollo muerto.A continuación, inicio de agitarlo.

En serio, no he encontrado una manera consistente para el seguimiento de estos tipos de errores.Porque hay tantos problemas potenciales, no hay una simple lista de comprobación para ir a través de.Sin embargo, yo recomendaría los siguientes:

  1. Póngase cómodo en un depurador.
  2. Inicio aporreando todo en el depurador para ver si usted puede encontrar cualquier cosa que parezca sospechosa.Compruebe especialmente para ver lo que pasa durante el exampleString = hello; de la línea.
  3. Compruebe para asegurarse de que realmente se estrellan en la exampleString = hello; línea, y no cuando sale de algunos adjuntando bloque (que podría causar destructores de fuego).
  4. Compruebe cualquier puntero de la magia que puede estar haciendo.Aritmética de punteros, de fundición, etc.
  5. Comprobar todas sus asignaciones y deallocations para asegurarse de que están emparejados (no hay doble deallocations).
  6. Asegúrese de que no haya devolución de las referencias o punteros a objetos en la pila.

Hay un montón de otras cosas para probar, también.Estoy seguro de que algunas otras personas en consonancia con las ideas así.

Algunos lugares para empezar:

Si estás en windows, y el uso de visual C++6 (espero que a dios nadie lo usa en estos días) es implentation de std::string no es seguro para subprocesos, y que puede conducir a este tipo de cosas.

He aquí un artículo que he encontrado que explica muchas de las causas comunes de pérdidas de memoria y la corrupción.

En mi anterior trabajo hemos utilizado Compuware Boundschecker para ayudar con esto.Es comercial y muy caros, por lo que no puede ser una opción.

He aquí un par de bibliotecas gratuitas que pueden ser de alguna utilidad

http://www.codeguru.com/cpp/misc/misc/memory/article.php/c3745/

http://www.codeproject.com/KB/cpp/MemLeakDetect.aspx

Espero que ayude.Corrupción de memoria es un sucky lugar para estar.

Podría ser daños en el montón, pero es igual de probable a ser la pila de la corrupción.Jim derecho.Realmente necesitamos un poco más de contexto.Esas dos líneas de código fuente no nos dicen mucho en el aislamiento.Podría ser cualquier número de cosas causante de este (que es el verdadero gozo de la C/C++).

Si usted se siente cómodo en la publicación de su código, usted puede incluso tirar todo en un servidor y después de un enlace.Estoy seguro que te entra mucha más consejos de esa manera (algunas de ellas, sin duda, relacionado a tu pregunta).

El código era simplemente un ejemplo de donde mi programa estaba fallando (que le fue asignada en la pila, Jim).No estoy realmente buscando '¿qué he hecho mal', sino '¿cómo diagnosticar lo que he hecho mal'.Enseñar a un hombre a pescar y todo eso.Aunque mirando a la pregunta, yo no he hecho eso bastante claro.Gracias a dios por la función de edición.:')

También, de hecho, me fijo el std::string problema.Cómo?Por su sustitución por un vector, la compilación, a continuación, reemplace la cadena de nuevo.Es fue siempre se bloquea, y que fija aunque...no podía.Hay algo desagradable que hay, y no estoy seguro de qué.Quería comprobar el tiempo me manualmente asignar memoria en el montón, a pesar de que:

 this->map = new Area*[largestY + 1];
 for (int i = 0; i < largestY + 1; i++) {
     this->map[i] = new Area[largestX + 1];
 }

y eliminarlo:

for (int i = 0; i < largestY + 1; i++) {
    delete [] this->map[i];
}
delete [] this->map;

No he asignado una matriz 2d con C++ antes.Parece que funciona.

También, de hecho, me fijo el std::string problema.Cómo?Por su sustitución por un vector, la compilación, a continuación, reemplace la cadena de nuevo.Fue consistentemente estrellarse allí, y que fija aunque...no podía.Hay algo desagradable que hay, y no estoy seguro de qué.

Eso suena como que realmente hizo temblar un pollo en ella.Si usted no sabe por qué ahora funciona, entonces es aún roto, y prácticamente garantizado para morder de nuevo más tarde (después de haber añadido aún más la complejidad).

Ejecutar Purificar.

Es casi una herramienta mágica que le informe cuando se clobbering memoria no te puede tocar, pérdida de memoria por no liberar cosas, liberación doble, etc.

Funciona en la máquina a nivel de código, así que usted no tiene que tener el código fuente.

Uno de los más agradables proveedor de llamadas de conferencia vez fui fue cuando Purificar encontró una pérdida de memoria en su código, y que hemos sido capaces de preguntar, "¿es posible que usted no liberar memoria en su función foo()" y escuchar el asombro en su voz.

Ellos pensaban que eran la depuración de los dioses, pero, a continuación, los dejamos en el secreto para que pudieran ejecutar Purificar antes teníamos que usar su código.:-)

http://www-306.ibm.com/software/awdtools/purify/unix/

(Es bastante caro, pero tienen un free eval descargar)

Una de las técnicas de depuración que uso frecuentemente (excepto en los casos de la más extrema rareza) es dividir y conquistar.Si el programa falla en la actualidad con algunos de error específico, luego se dividen en mitad de alguna manera y ver si aún tiene el mismo error.Obviamente el truco es decidir donde dividir su programa!

El ejemplo dado no muestran suficiente contexto para determinar dónde puede estar el error.Si nadie fuera a tratar de su ejemplo, de que iba a funcionar bien.Así, en su programa, tratar de eliminar la mayor cantidad de material adicional que no nos muestran y ver si funciona, a continuación,.Si es así, a continuación, añadir el otro código nuevo en un poco a la vez hasta que empieza a fallar.Entonces, la cosa acaba de agregar es probablemente el problema.

Tenga en cuenta que si su programa es multiproceso, entonces usted probablemente tiene problemas más grandes.Si no, entonces usted debería ser capaz de reducir de esta manera.Buena suerte!

Otras de las herramientas como Boundschecker o Purificar, su mejor apuesta en la resolución de problemas como este es que se acaba de conseguir realmente bueno en la lectura de códigos y familiarizarse con el código que estás trabajando.

Corrupción de memoria es una de las cosas más difíciles de solucionar y por lo general, estos tipos de problemas son resueltos por el gasto de horas/días en un depurador y notando algo como "hey, puntero X se utiliza después de haber sido eliminado!".

Si esto ayuda, es algo que mejorar en la medida que adquiera experiencia.

Su asignación de memoria para la matriz es la correcta, pero asegúrese de comprobar todos los lugares donde tiene acceso a la matriz demasiado.

El código que puedo ver que no tiene errores.Como se ha dicho más contexto es necesario.

Si ya has probado, instalar gdb (gcc depurador) y compilar el programa con-g.Esto compilará en símbolos de depuración que gdb puede utilizar.Una vez que haya gdb instalado lo ejecutas con el programa (gdb ). Este es una útil cheatsheat para el uso de gdb.

Establezca un punto de interrupción para la función a la que está produciendo el error, y ver lo que el valor de exampleString es.También hacer lo mismo para cualquiera que sea el parámetro que se pasa a exampleString.Esto debería al menos decir si el std::cadenas de caracteres son válidos.

He encontrado la respuesta de este artículo para ser una buena guía acerca de los punteros.

Como lo que puedo decir que el código es correcto.Suponiendo exampleString es un std::string que tiene el ámbito de la clase como la que usted describe, usted debería ser capaz de inicializar/asignar esa manera.Tal vez hay algún otro problema?Tal vez un fragmento de código real podría ayudar a poner en contexto.

Pregunta:Es exampleString un puntero a una cadena de objeto creado con new?

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top