我是c ++的新手,在玩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 ++版本:
aalen@CFC: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
编译我的代码。感谢您的关注,对不起我糟糕的英语。
似乎因为我在IntervalToCheck类中使用GiNaC而且它不是线程安全的(因为我用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,如n.m所示。也许GiNaC就是问题所在。如果任何人都可以提供一个用于处理表达的开放工具,那就太好了。 thx for reading。
答案 0 :(得分:0)
如果您查看源代码中出现分段错误的位置,您可以从GiNaC的reference counting pointer实现中看到它。根据我的理解,问题在于,当另一个线程仍在使用它时,指针可能会被过早删除。这是因为对于线程访问,计数器上的递增和递减操作不是原子的。因此,您正在尝试访问已删除的内存,这是未定义的行为(因此是段错误的)。
实际上,过去似乎出现了这个问题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>
或类似的东西,那么该程序可能会起作用,或者您可以使用具有原子引用计数的另一个实现。
至于您编写的实际代码,它似乎应该可以正常工作。尽管print语句可以按顺序执行和交错,但它们似乎在关键块中被正确锁定,尽管在C ++中使用更具惯用性,RAII增强的std::scoped_lock
可能更好。