Search code examples
cpointersundefined-behaviordereference

Dereferencing pointer cast from an integer of a valid memory address give Segmentation fault


I was playing around with c pointer and wrote this code

#include <stdio.h>

int main() {
    int a = 17;
    int* p1 = &a;
    int* p2 = (int*)(&p1);
    p1 = (int*)(&p2);
    printf("%d\n", *((int*)(*p1)));
    printf("%d\n", *((int*)(*p2)));
    return 0;
}

the program exit with

[Done] exited with code=3221225477 in 0.23 seconds

the pointers work as expected

#include <stdio.h>

int main() {
    int a = 17;
    int* p1 = &a;
    int* p2 = (int*)(&p1);
    p1 = (int*)(&p2);
    printf("&p1 %d\n", &p1);
    printf("&p2 %d\n", &p2);
    printf("p1 %d\n", p1);
    printf("p2 %d\n", p2);
    printf("*p1 %d\n", *p1);
    printf("*p2 %d\n", *p2);
    // printf("%d\n", *((int*)(*p1)));
    // printf("%d\n", *((int*)(*p2)));
    return 0;
}
&p1 748680992
&p2 748680984
p1 748680984
p2 748680992
*p1 748680992
*p2 748680984

it only stopped working when i try to dereference arbitrary-ish address

according to the answers from another question, the reason dereferencing arbitrary memory address doesn't work is because the address is invalid

but here i dereference an address that i was able to dereference just fine before

is this because of some kind of protection to prevent bad code? if so i want to know the specifics of the protection mechanism or i'm just doing it wrong for what i'm trying to achieve?


Solution

  • I figured it out but forgot to post the answer

    because the size of int is smaller than the size of int*, i can't fit the entire value of &p1 inside of p1

    i solve this issue by changing from int* to long long* because long long and long long* have the same byte size on my system

    #include <stdio.h>
    
    int main() {
        long long a = 17;
        long long* p1 = &a;
        long long* p2 = (long long*)(&p1);
        p1 = (long long*)(&p2);
        printf("&p1 %d\n", &p1);
        printf("&p2 %d\n", &p2);
        printf("p1 %d\n", p1);
        printf("p2 %d\n", p2);
        printf("*p1 %d\n", *p1);
        printf("*p2 %d\n", *p2);
        printf("%d\n", *((long long*)(*p1)));
        printf("%d\n", *((long long*)(*p2)));
        return 0;
    }
    

    output:

    &p1 1848453792
    &p2 1848453784
    p1 1848453784
    p2 1848453792
    *p1 1848453792
    *p2 1848453784
    1848453784
    1848453792
    

    I was trying to create 2 pointers that point to each others to see if i can indefinitely dereference the pointer, and it definitely can