c++ linux g++ pthreads segmentation-fault

C++ libpthread programa segfaults por razones desconocidas



linux g++ (2)

¿Tiene acceso a Helgrind en su plataforma? Es una herramienta de Valgrind para detectar errores de subprocesos de POSIX, como las razas y los hilos que retienen mutexes cuando salen.

Tengo una aplicación vinculada libpthread. El núcleo de la aplicación son dos FIFO compartidos por cuatro hilos (dos hilos por cada FIFO que es;). La clase FIFO se sincroniza utilizando pthread mutexes y almacena punteros a clases grandes (que contienen almacenamientos intermedios de aproximadamente 4kb de tamaño) asignados dentro de la memoria estática usando operadores nuevos y eliminados sobrecargados (no hay asignación dinámica aquí).

El programa en sí mismo generalmente funciona bien, pero de vez en cuando se segmenta sin motivo aparente. El problema es que no puedo depurar correctamente los segmentos, ya que estoy trabajando en un sistema integrado con un antiguo kernel de Linux (2.4.29) y g ++ (versión gcc egcs-2.91.66 19990314 / Linux (egcs-1.1. 2 lanzamiento)).

No hay gdb en el sistema, y ​​no puedo ejecutar la aplicación en otro lugar (es demasiado específico del hardware).

Recopilé la aplicación con indicadores -g y -rdynamic, pero un gdb externo no me dice nada cuando examino el archivo central (solo direcciones hexadecimales) - aún puedo imprimir la traza inversa del programa después de capturar SIGSEGV - siempre se ve así:

Backtrace for process with pid: 6279 -========================================- [0x8065707] [0x806557a] /lib/libc.so.6(sigaction+0x268) [0x400bfc68] [0x8067bb9] [0x8067b72] [0x8067b25] [0x8068429] [0x8056cd4] /lib/libpthread.so.0(pthread_detach+0x515) [0x40093b85] /lib/libc.so.6(__clone+0x3a) [0x4015316a] -========================================- End of backtrace

Entonces parece apuntar a libpthread ...

Ejecuté algunos de los módulos a través de valgrind, pero no encontré ninguna pérdida de memoria (ya que apenas utilizo una asignación dinámica).

Pensé que quizás los mutex causan algunos problemas (ya que se bloquean / desbloquean unas 200 veces por segundo), así que cambié mi clase mutex simple:

class AGMutex { public: AGMutex( void ) { pthread_mutex_init( &mutex1, NULL ); } ~AGMutex( void ) { pthread_mutex_destroy( &mutex1 ); } void lock( void ) { pthread_mutex_lock( &mutex1 ); } void unlock( void ) { pthread_mutex_unlock( &mutex1 ); } private: pthread_mutex_t mutex1; };

a una clase mutex muda:

class AGMutex { public: AGMutex( void ) : mutex1( false ) { } ~AGMutex( void ) { } volatile void lock( void ) { if ( mutex1 ) { while ( mutex1 ) { usleep( 1 ); } } mutex1 = true; } volatile void unlock( void ) { mutex1 = false; } private: volatile bool mutex1; };

pero no cambió nada y la traza inversa se ve igual ...

Después de una sesión de depuración de old-school put-cout-between-every-line-and-see-where-it-segfaults-plus-remember-the-pids-and-stuff, parece que segfaults durante usleep (?).

No tengo idea de qué más podría estar mal. Puede funcionar durante una hora más o menos, y luego segfault repentinamente sin razón aparente.

¿Alguien ha encontrado un problema similar?


De mi respuesta a Cómo generar un stacktrace cuando mi aplicación gcc C ++ falla :

The first two entries in the stack frame chain when you get into the signal handler contain a return address inside the signal handler and one inside sigaction() in libc. The stack frame of the last function called before the signal (which is the location of the fault) is lost.

Esto puede explicar por qué tiene dificultades para determinar la ubicación de su segfault a través de una traza inversa desde un manejador de señal. Mi respuesta también incluye una solución para esta limitación.

Si desea ver cómo se distribuye realmente su aplicación en la memoria (es decir, direcciones 0x80..... ), debe poder generar un archivo de mapa de gcc. Esto normalmente se realiza a través de -Wl,-Map,output.map , que pasa -Map output.map al enlazador.

También puede tener una versión específica de hardware de objdump o nm con su cadena de herramientas / herramienta cruzada que puede ser útil para descifrar sus direcciones 0x80..... .