Estoy escribiendo un programa C ++ multiplataforma para Windows y Unix. En el lado de la ventana, el código se compilará y ejecutará sin problemas. En el lado de Unix, se compilará; sin embargo, cuando intento ejecutarlo, aparece un error de segmentación. Mi corazonada inicial es que hay un problema con los punteros.
¿Cuáles son las buenas metodologías para encontrar y corregir errores de falla de segmentación?
fuente
g
en el contexto deCMake
?cmake -DCMAKE_BUILD_TYPE=Debug
.A veces, el bloqueo en sí no es la causa real del problema; tal vez la memoria se rompió en un momento anterior, pero la corrupción tardó un tiempo en mostrarse. Eche un vistazo a valgrind , que tiene muchas comprobaciones para detectar problemas de punteros (incluida la comprobación de límites de matriz). Le dirá dónde comienza el problema , no solo la línea donde ocurre el accidente.
fuente
Antes de que surja el problema, intente evitarlo tanto como sea posible:
Utilice las herramientas adecuadas para la depuración. En Unix:
Con GCC también puedes usar mudflapCon GCC, Clang y desde octubre de forma experimental MSVC puedes usar Address / Memory Sanitizer . Puede detectar algunos errores que Valgrind no detecta y la pérdida de rendimiento es menor. Se usa compilando con la-fsanitize=address
bandera.Finalmente recomendaría las cosas habituales. Cuanto más legible, fácil de mantener, claro y ordenado sea su programa, más fácil será depurarlo.
fuente
En Unix puede usar
valgrind
para encontrar problemas. Es gratis y poderoso. Si prefiere hacerlo usted mismo, puede sobrecargar los operadoresnew
ydelete
para establecer una configuración en la que tenga 1 byte0xDEADBEEF
antes y después de cada nuevo objeto. Luego, realice un seguimiento de lo que sucede en cada iteración. Esto puede fallar en capturar todo (no se garantiza que siquiera toque esos bytes) pero me ha funcionado en el pasado en una plataforma Windows.fuente
new
ydelete
puede ser muy útil, usarlo-fsanitize=address
es una mejor opción ya que el compilador compilará en tiempo de ejecución para detectar problemas y volcará la memoria automáticamente a la pantalla, lo que facilita la depuración.Sí, hay un problema con los punteros. Es muy probable que esté utilizando uno que no se haya inicializado correctamente, pero también es posible que esté arruinando la gestión de su memoria con dobles liberaciones o algo así.
Para evitar punteros no inicializados como variables locales, intente declararlos lo más tarde posible, preferiblemente (y esto no siempre es posible) cuando puedan inicializarse con un valor significativo. Convénzase de que tendrán un valor antes de que se utilicen, examinando el código. Si tiene dificultades con eso, inicialícelos a una constante de puntero nulo (generalmente escrito como
NULL
o0
) y verifíquelos.Para evitar punteros no inicializados como valores de miembros, asegúrese de que estén inicializados correctamente en el constructor y se manejen correctamente en los constructores de copia y los operadores de asignación. No confíe en una
init
función para la gestión de la memoria, aunque puede hacerlo para otras inicializaciones.Si su clase no necesita constructores de copia u operadores de asignación, puede declararlos como funciones miembro privadas y nunca definirlos. Eso provocará un error del compilador si se utilizan explícita o implícitamente.
Utilice punteros inteligentes cuando corresponda. La gran ventaja aquí es que, si se adhiere a ellos y los usa de manera consistente, puede evitar completamente la escritura
delete
y nada se eliminará dos veces.Utilice cadenas de C ++ y clases de contenedor siempre que sea posible, en lugar de cadenas y matrices de estilo C. Considere usar en
.at(i)
lugar de[i]
, porque eso forzará la verificación de límites. Vea si su compilador o biblioteca se puede configurar para verificar límites[i]
, al menos en modo de depuración. Las fallas de segmentación pueden ser causadas por saturaciones de búfer que escriben basura sobre punteros perfectamente buenos.Hacer esas cosas reducirá considerablemente la probabilidad de fallas de segmentación y otros problemas de memoria. Sin duda fallarán en arreglarlo todo, y es por eso que debería usar valgrind de vez en cuando cuando no tenga problemas, y valgrind y gdb cuando los tenga.
fuente
No conozco ninguna metodología que se pueda utilizar para solucionar este tipo de problemas. No creo que sea posible encontrar uno, ya que el problema en cuestión es que el comportamiento de su programa no está definido (no conozco ningún caso en el que SEGFAULT no haya sido causado por algún tipo de UB) .
Existen todo tipo de "metodologías" para evitar el problema antes de que surja. Uno importante es RAII.
Además de eso, solo tienes que ponerle tus mejores energías psíquicas.
fuente