对于以下代码:
#include<stdatomic.h>
int *sp;
int threadFunc()
{
int *p;
for(int i = 0; i < 10; i++){
p = __atomic_load_n(&sp+i, __ATOMIC_SEQ_CST);
printf("Value loaded = %d from %p", *p, p);
}
return 0;
}
int main(int argc, char *argv[])
{
int a = 0;
sp = malloc(sizeof(int)*10);
if(sp == NULL){
printf("Not enough memoryn");
return -1;
}
// initialize the contiguous array pointed by sp with zero
for(int i = 0; i < 10; i++){
memcpy((void*)sp+i, &a, sizeof(int));
}
// call the following function on different thread
threadFunc();
return 0;
}
我在threadFunc()
中得到分段错误。程序打印正确的i=0
,但给出了一个分割错误的所有i > 0
。我哪里做错了?
你应该在这里提供一个指向对象的指针:
_atomic_load_n(&sp+i, __ATOMIC_SEQ_CST);
这不是正确的事情:
&sp + i
上面取sp
的地址,加上i
,指向…没有int*
存储的地方。此外,您希望从int
加载,而不是int*
。
修复方法是:
int threadFunc() {
int p; // not an int*
for(int i = 0; i < 10; i++){
p = atomic_load_explicit(sp + i, memory_order_seq_cst); // not &sp + i
// or: p = __atomic_load_n(sp + i, __ATOMIC_SEQ_CST);
printf("Value loaded = %dn", p);
}
return 0;
}
(我只是用相应的标准调用替换了这个调用)
同样,使用memset
设置您分配的资源:
memset(sp, 0, sizeof(int) * 10);
演示int main
将无法编译。main
原型的最小签名为:
int main(void);
所示代码中的另一个问题是对memcpy()的不正确使用。它不需要循环使用:
改变:
for(int i = 0; i < 10; i++){
memcpy((void*)sp+i, &a, sizeof(int));
}
memset(sp, 0, 10* sizeof(int));
最后,对表达式进行整型:
int *p;
for(int i = 0; i < 10; i++){
p = __atomic_load_n(&sp+i, __ATOMIC_SEQ_CST);
printf("Value loaded = %d from %p", *p, p);
}
p
是一个指针,但是它指向某个还不属于进程的位置。写入它是一种未定义的行为,并且很可能导致您的段错误。