全局静态布尔指针导致使用PTHREAD导致分割故障
-
24-10-2019 - |
题
PTHread编程的新功能,并在处理C ++和C混合代码时遇到了此错误。
我所做的是调用C ++代码创建的线程中的C代码。有一个静态布尔指针 is_center
线程在线程中使用,当线程完成时应获得自由。
但是,我注意到每次处理到C函数中的程序时,布尔指针的值都会更改,并且由于免费()而发生分割故障。问题只有在使用C代码时才发生。删除C代码,多线程C ++零件效果很好。
详细代码如下:
static bool *is_center;
// omit other codes in between ...
void streamCluster( PStream* stream)
{
// some code here ...
while(1){
// some code here ...
is_center = (bool*)calloc(points.num,sizeof(bool));
// start the parallel thread here.
// the c code is invoked in this function.
localSearch(&points,kmin, kmax,&kfinal); // parallel
free(is_center);
}
并且使用并行的功能如下(在每个线程中调用我的C代码):
void localSearch( Points* points, long kmin, long kmax, long* kfinal ) {
pthread_barrier_t barrier;
pthread_t* threads = new pthread_t[nproc];
pkmedian_arg_t* arg = new pkmedian_arg_t[nproc];
pthread_barrier_init(&barrier,NULL,nproc);
for( int i = 0; i < nproc; i++ ) {
arg[i].points = points;
arg[i].kmin = kmin;
arg[i].kmax = kmax;
arg[i].pid = i;
arg[i].kfinal = kfinal;
arg[i].barrier = &barrier;
pthread_create(threads+i,NULL,localSearchSub,(void*)&arg[i]);
}
for ( int i = 0; i < nproc; i++) {
pthread_join(threads[i],NULL);
}
delete[] threads;
delete[] arg;
pthread_barrier_destroy(&barrier);
}
最后,调用我的C代码的功能:
void* localSearchSub(void* arg_) {
int eventSet = PAPI_NULL;
begin_papi_thread(&eventSet);
pkmedian_arg_t* arg= (pkmedian_arg_t*)arg_;
pkmedian(arg->points,arg->kmin,arg->kmax,arg->kfinal,arg->pid,arg->barrier);
end_papi_thread(&eventSet);
return NULL;
}
从GDB,我得到了 is_center
是:
Breakpoint 2, localSearchSub (arg_=0x600000000000bc40) at streamcluster.cpp:1711
1711 end_papi_thread(&eventSet);
(gdb) s
Hardware watchpoint 1: is_center
Old value = (bool *) 0x600000000000bba0
New value = (bool *) 0xa93f3
0x400000000000d8d1 in localSearchSub (arg_=0x600000000000bc40) at streamcluster.cpp:1711
1711 end_papi_thread(&eventSet);
有什么建议么?提前致谢!
有关该代码的一些新信息:对于C代码,我正在使用Papi软件包。我编写自己的Papi包装器来初始化和读取系统计数器。代码如下:
void begin_papi_thread(int* eventSet)
{
int thread_id = pthread_self();
// Events
if (PAPI_create_eventset(eventSet)) {
PAPI_perror(return_value, error_string, PAPI_MAX_STR_LEN);
printf("*** ERROR *** Failed to create event set for thread %d: %s\n.", thread_id, error_string);
}
if((return_value = PAPI_add_events(*eventSet, event_code, event_num)) != PAPI_OK)
{
printf("*** ERROR *** Failed to add event for thread %d: %d.\n", thread_id, return_value);
}
// Start counting
if ((return_value = PAPI_start(*eventSet)) != PAPI_OK) {
PAPI_perror(return_value, error_string, PAPI_MAX_STR_LEN);
printf("*** ERROR *** PAPI failed to start the event for thread %d: %s.\n", thread_id, error_string);
}
}
void end_papi_thread(int* eventSet)
{
int thread_id = pthread_self();
int i;
long long * count_values = (long long*)malloc(sizeof(long long) * event_num);
if (PAPI_read(*eventSet, count_values) != PAPI_OK)
printf("*** ERROR *** Failed to load count values.\n");
if (PAPI_stop(*eventSet, &dummy_values) != PAPI_OK) {
PAPI_perror(return_value, error_string, PAPI_MAX_STR_LEN);
printf("*** ERROR *** PAPI failed to stop the event for thread %d: %s.\n", thread_id, error_string);
return;
}
if(PAPI_cleanup_eventset(*eventSet) != PAPI_OK)
printf("*** ERROR *** Clean up failed for the thread %d.\n", thread_id);
}
解决方案
我认为您没有发布足够的代码来真正理解您的问题,但是您已声明了 is_center
全球的。我认为您在多个线程中使用了多个地方(可能是多个线程)(localSearchSub
提到,这是您的工作线程功能)。
如果 is_center
正在由多个线程读取或编写,您可能想用一个 pthread Mutex. 。您说它是“线程完成后释放”的,但是您应该知道 nprocs
线程,看起来他们都在工作 is_center[points]
布尔。如果 points != nproc
, ,这可能是坏事[1]。每个线程可能应自行使用,并且 localSearch
应该汇总结果。
这 xxx_papi_thread
功能在Google上没有任何命中,因此我只能想象这是您自己的...如果问题出现在那里,我们不太可能能为您提供帮助:)
1]:即使 points == nproc
, ,不一定可以从多个线程(它的编译器和处理器依赖性)写入数组的不同元素。安全,请使用互斥。
另外,这是标记的 C++
. 。你能替换 calloc
和动态数组(使用 new
) 和 vector
s?它可能最终更容易调试,并且当然最终更容易维护。您为什么讨厌并想惩罚代码的读者? )