C语言 指针数组的分段错误



对于以下代码:

#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是一个指针,但是它指向某个还不属于进程的位置。写入它是一种未定义的行为,并且很可能导致您的段错误。