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

Мой код:

#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

5 ответов

Решение

Чистое везение. Поведение в этом случае не определено. То есть: нельзя ожидать, что произойдет.

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

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

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

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

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

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

это возможно с неопределенным поведением

Вы отображаете адрес памяти 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; работать как статическое назначение, хотя это неопределенное поведение.

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

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

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

Другие вопросы по тегам