Почему мой висячий указатель не вызывает ошибку сегментации?

Мой код:

#include <stdio.h>
#include <stdlib.h>

int main(void) {
    int *p = (int *)malloc(sizeof(int));
    free(p);
    *p = 42;
    return 0;
}

Я создал указатель, затем я указал его на выделенное пространство, и, наконец, я назначил ему 42. По-моему, это не должно работать, это должно вызвать ошибку сегментации, но она работает. Итак, почему?

PS: Я обычно скомпилировал его с помощью Gcc на Linux

Ответ 1

Удачи. Поведение в этом случае undefined. I.e: нет ожиданий относительно того, что может произойти.

Ответ 2

По-моему, он не должен работать [...], но он работает.

Не волнуйтесь, это не сработает.

он должен вызвать ошибку сегментации

Расскажите об этом комитету по стандартам С. Это просто поведение undefined, оно не требуется для сбоя.

Ответ 3

Более сложный ответ, помимо "undefined", заключается в том, что вы можете писать в произвольные ячейки памяти в C, пока вы остаетесь в пределах выделенных процессов. В зависимости от ОС может быть разрешен код перезаписи. Болезненные эффекты появляются только после того, как какой-то другой код вашего процесса запутался в том, что обнаружено в искаженной памяти. Так как ваша программа выходит сразу после испорчения памяти, вероятность того, что некоторые из ее кода будут запутаны, явно мала.

Ответ 4

Поведение в этом случае undefined,

это возможность с поведением undefin

Ответ 5

вы отображаете адрес памяти p до и после бесплатной проверки "p" с помощью:

#include <stdio.h>
#include <stdlib.h>

    int main(void) {
        int *p = (int *)malloc(sizeof(int));
         printf("before \n %p \n",p);
         free(p);
        *p = 42;
         printf("after\n %p \n",p);
         printf(" %d \n",*p);
        return 0;
    }

до и после свободного мы имеем одну и ту же адресную память, потому что free() не присваиваем NULL p-указателю, поэтому *p = 42; работает как статическое присваивание, хотя это поведение undefined.

предложите использовать БЕСПЛАТНЫЙ макрос:

#define FREE(X) \
free(X);\
X=NULL;

проверьте этот макрос, и вы увидите ожидаемое поведение