2010-02-22 134 views
1

我有一個libpthread鏈接的應用程序。該應用程序的核心是由四個線程共享的兩個FIFO(每個FIFO有兩個線程)。 FIFO類使用pthread互斥體進行同步,它使用重載的新運算符和刪除運算符(此處不包含動態分配)存儲指向靜態內存中分配給大類(包含大小約4kb的緩衝區)的指針。C++ libpthread程序段錯誤原因不明

該程序本身通常工作正常,但不時看到段故障沒有明顯的原因。問題是,我無法正確調試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調試會話似乎在usleep(?)中發生段錯誤。

我不知道還有什麼可能是錯的。它可以工作一個小時左右,然後突然發生段故障,沒有明顯的原因。

有沒有人遇到類似的問題?

+0

你使用線程屬性?手動分離線程? – 2010-02-22 16:19:29

+0

@Nikolai N Fetissov:不,這只是pthread_create與NULL作爲第二個參數傳遞,然後pthread_exit - > pthread_join – zajcev 2010-02-22 17:09:55

回答

1

從我answerHow 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. 

這也許可以解釋爲什麼你通過從信號處理回溯確定你的段錯誤的位置困難。我的answer也包含解決此限制的解決方法。

如果你想看看如何實際應用程序在內存佈局(即0x80.....地址),你應該能夠產生從GCC中地圖文件。這通常通過-Wl,-Map,output.map完成,它將-Map output.map傳遞給鏈接器。

您可能還有一個特定於硬件的版本objdumpnm與您的工具鏈/交叉工具鏈,這可能有助於破譯您的0x80.....地址。

+0

謝謝,我明天會試試這個 – zajcev 2010-02-22 17:17:54

0

您是否有權訪問您的平臺上的Helgrind?這是一個Valgrind工具,用於檢測POSIX線程錯誤,比如退出時持有互斥體的比賽和線程。