2013-02-25 102 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可能更好。