pthread编程的新手,并且在C++ & C混合代码上工作时出现此错误。全局静态布尔指针使用pthread导致段错误
我所做的就是调用由C++代码创建的线程中的c代码。在线程中使用了一个静态布尔指针is_center
,并且在线程结束时应该可用。
但是我注意到,每当程序处理到c函数中时,布尔指针的值都会改变,然后由于free()而发生分段错误。只有在使用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);
}
代码不足。 'localSearchSub()'中有什么?尽管如此,你仍然处于正确的轨道上。仔细查看'streamcluster.cpp:1711'周围的代码,检查数组是否超出/低于运行,任何指针操作。尽量简化所有步骤清晰可见的步骤。 – 2010-06-06 01:43:44
问题出现在我使用的c代码上。我使用PAPI API来捕获每个线程中的硬件计数器,因此我编写了一个如上所述的包装来初始化它并开始捕获。 我发现在我的调试过程中,调用'end_papi_thread'后'is_center'的地址被改变了,然后分段错误被'free(is_center)'触发了。删除我的papi包装代码后,一切正常。 所以我很困惑地址的更新。 '免费(is_center)'应该在主线程的上下文中工作在我看来,但它似乎在线程上下文... – asksw0rder 2010-06-06 03:38:34