1

For the following code:

#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 memory\n");
        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;
}

I am getting a segmentation fault in threadFunc(). The program prints correctly for i=0, but gives a segmentation fault for all i > 0. Where is it that I am going wrong?

16
  • 1
    You don't need to cast to void*. (and there is no array of pointers present in your program) Commented Sep 30, 2021 at 13:40
  • 2
    That int main{ looks wonky - what compiler are you using? If this is supposed to be standard C, please test to compile your code before posting. Commented Sep 30, 2021 at 13:43
  • 1
    @RestingPlatypus: No, you didn't. Commented Sep 30, 2021 at 13:44
  • 2
    Please put code up that you actually can compile yourself. If this actually compiles for you, please mention what compiler (and options) you are using. Commented Sep 30, 2021 at 13:45
  • 2
    &sp+i is not what you want. It takes the address of sp and adds i to it. But there are no other pointer after the single one. Commented Sep 30, 2021 at 13:47

2 Answers 2

3

You are supposed to supply a pointer to the object here:

_atomic_load_n(&sp+i, __ATOMIC_SEQ_CST);

This is not the correct thing:

&sp + i

The above takes the address of sp and adds i, pointing ... somewhere where you have no int* stored. Also, you want to load from an int, not an int*.

A fix would be:

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 = %d\n", p);
    }
    return 0;
}

(I just replaced the call with the corresponding standard call)

Also, use memset to set what you allocated:

memset(sp, 0, sizeof(int) * 10);

Demo

Sign up to request clarification or add additional context in comments.

2 Comments

Thanks a lot for this! I tried a similar approach, but I was setting something like int **p followed by p = &sp and then replacing &sp+i by p[i], and that didn't work.
@RestingPlatypus You're welcome. I guess you may have made an addition to the pointer erroneously so that it ends up pointing out of bounds. All the **'s makes it tricky.
2
int main 

will not compile. The minimum signature of the main prototype is:

int main(void);

Another problem in the code shown is incorrect use of memcpy(). It does not require a loop use:

Change this:

   for(int i = 0; i < 10; i++){
        memcpy((void*)sp+i, &a, sizeof(int));
   }

to this

memset(sp, 0, 10* sizeof(int));

Finally, int the expression:

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 is a pointer, but it points to some location that is not yet owned by your process. Writing to it is undefined behavior, and likely the cause of your seg-fault.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.