2010-02-22 4 views
1

У меня есть приложение, связанное с libpthread. Ядром приложения являются два FIFO, разделяемых четырьмя потоками (два потока на один FIFO, который есть;). Класс FIFO синхронизируется с использованием мьютексов pthread, и он хранит указатели на большие классы (содержащие буферы размером около 4kb), выделенные внутри статической памяти, с использованием перегруженных операторов new и delete (здесь нет динамического выделения).C++ libpthread программа segfaults по неизвестной причине

Программа сама по себе работает нормально, но время от времени она segfaults без видимой причины. Проблема в том, что я не могу отлаживать segfaults правильно, поскольку я работаю над встроенной системой со старым ядром Linux (2.4.29) и g ++ (версия gcc egcs-2.91.66 19990314/Linux (egcs-1.1. 2 релиз)).

В системе нет gdb, и я не могу запустить приложение в другом месте (это слишком специфично для оборудования).

Я скомпилировал приложение с флагами -g и -rdynamic, но внешний gdb ничего мне не говорит, когда я просматриваю основной файл (только шестнадцатеричные адреса) - все же я могу распечатать обратную трассировку из программы после того, как поймал SIGSEGV - он всегда выглядит следующим образом:

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 

так что, похоже, указывает на libpthread ...

Я побежал некоторые из модулей через Valgrind, но я не нашел каких-либо утечек памяти (как я едва используя любое динамическое распределение).

Я подумал, что может быть, мьютексы вызывает некоторые проблемы (по мере их блокировки/разблокировки около 200 раз в секунду), так что я переключил свой простой класс мьютекс:

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; 

}; 

к фиктивной класса мьютекса:

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; 

}; 

, но это ничего не изменило и трассировку выглядит так же ...

После некоторых oldchool пут-COUT-между-каждый-линии и наблюдать, где-то-плюс-ошибку сегментации -remember-the-pids-and-stuff отладочный сеанс, кажется, что он segfaults во время usleep (?).

Я понятия не имею, что еще может быть неправильно. Он может работать в течение часа или около того, а затем внезапно segfault без видимых причин.

Неужели кто-нибудь сталкивался с подобной проблемой?

+0

Вы используете атрибуты нитей? Отсоединение потоков вручную? –

+0

@Nikolai N Fetissov: Нет, это просто pthread_create с NULL, переданным как второй аргумент, а затем pthread_exit -> pthread_join – zajcev

ответ

1

От моего answer к How to generate a stacktrace when my gcc C++ app crashes:

 
    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. 

Это может объяснить, почему у вас возникают трудности, определяющие местонахождение вашего Segfault через трассировку из обработчика сигнала. Мой answer также включает в себя обходной путь для этого ограничения.

Если вы хотите увидеть, как ваше приложение на самом деле выложено в памяти (т.е. 0x80..... адреса), вы должны быть в состоянии генерировать карты файл из НКИ. Обычно это делается через -Wl,-Map,output.map, который передает -Map output.map в компоновщик.

Возможно, у вас также есть аппаратная версия objdump или nm с вашей инструментальной пряжкой/кросс-цепочкой, которая может быть полезна при расшифровке адресов 0x80......

+0

Спасибо, я попробую это завтра – zajcev

0

У вас есть доступ к Helgrind на вашей платформе? Это инструмент Valgrind для обнаружения ошибок потока POSIX, таких как расы и потоки, содержащие мьютексы при их выходе.

Смежные вопросы