2013-02-25 100 views
1

我與C++是一個新手,我得到了一個「分段錯誤(核心轉儲)」與C++ 11的線程玩的時候。我修改了一段我以前寫的好的代碼,並得到了錯誤。我修改的部分是分段錯誤(核心轉儲)與C++ 11線程

mutex m; 
auto thread_f=[&](int i) 
{ 
    for(int j=i; j<interval.size(); j+=Threads_Number) 
    { 
     vector<Permutation >::iterator it1=(interval.begin()+j); 
     for(vector<Permutation >::iterator it2=it1; it2!=interval.end(); it2++) 
     { 
      if(!(*it1<*it2)) continue; 
      IntervalToCheck x(*it1,*it2); 
      m.lock(); 
      cout<<x; 
      f<<x; 
      m.unlock(); 
     } 
    } 
}; 

vector<thread> threads; 
threads.clear(); 
for(int i=0; i<Threads_Number; i++) 
    threads.push_back(thread(thread_f,i)); 
for(auto& th:threads) 
    th.join(); 

其中變量「f」是ofstream的一個對象。而且奇怪的是,當我「Threads_Number」設置爲1,程序運作良好,而當我設「Threads_Number」不是1,程序有時會工作得很好,有時並不---就像當我不初始化一個int舊時代並使用它。

這是我的G ++版本:

[email protected]:multiThreads> g++ --version           13-02-25 14:24 
g++ (GCC) 4.7.2 
Copyright (C) 2012 Free Software Foundation, Inc. 

我用的是:

g++ -c main.cpp --std=c++11 

g++ *.o -o work -lcln -lginac -pthread 

編譯我的代碼。感謝您的關注,對不起我的英文不好。

看來,因爲我在課堂上使用GiNaC IntervalToCheck,它不是線程安全的(因爲我用Google搜索GiNac和線程安全的),因爲我得到了

Program received signal SIGSEGV, Segmentation fault. 
[Switching to Thread 0x7ffff5340700 (LWP 3125)] 
0x00000000004097cf in GiNaC::ptr<GiNaC::basic>::operator= (this=0x7fffec000cd0, other=...) at /usr/include/ginac/ptr.h:88 
88    delete p; 

從GDB如牛米建議的消息。也許GiNaC是問題。如果任何人都可以提供處理表達的開放工具,那就太好了。 thx閱讀。

+3

學習如何使用調試器來解決崩潰。 'gdb your-program-name'應該讓你開始。 – 2013-02-25 06:44:06

+2

清除()一個空向量是沒有意義的。你不應該調用'm.lock()'和'm.unlock()',你應該使用其中一種標準的鎖類型 – 2013-02-25 10:27:04

回答

0

如果你看一下,其中分段錯誤是從哪裏來的源代碼,你可以看到它從GiNaC的實施reference counting pointer的是。這個問題,從我的理解是,它是可能的,而另一個線程仍在使用它的指針被過早刪除。這是因爲對於線程訪問而言,計數器上的遞增和遞減操作不是原子操作。因此,您正嘗試訪問已刪除的內存,這是未定義的行爲(因此可以進行segfault-able)。

事實上,看來這個問題在過去,and the concern was voiced on their mailing list彈起。

GiNaC is not thread-safe, according to its maintainer.

因此,你根本無法從多個線程使用GiNaC,如預期的維護者。

理論上,也許你可以用ginac::ptr代替std::shared_ptr之類的東西,它保證沒有關於引用計數機制的競爭條件。所以如果你可以用std::atomic<int>或類似的東西替換內部計數器類型,或者你可以使用另一個具有原子引用計數的實現,程序可能會工作。

至於你寫的實際代碼,它似乎應該工作正常。儘管打印語句可以按順序執行和交錯,但它們似乎在關鍵塊中被正確鎖定,儘管在C++中使用更慣用的RAII增強型std::scoped_lock可能更好。