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

Мой код:

#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.


person Andrea Ciceri    schedule 21.12.2013    source источник
comment
Вам не повезло. Всегда есть возможность с неопределенным поведением.   -  person David Heffernan    schedule 22.12.2013
comment
Не точный дубликат, поскольку этот вопрос помечен как C++, но см. stackoverflow.com/questions/6441218/   -  person Pascal Cuoq    schedule 22.12.2013
comment
Пожалуйста, прочитайте stackoverflow.com/questions/2346806/what-is-segmentation- ошибка   -  person James Black    schedule 22.12.2013


Ответы (5)


Чистое везение. В этом случае поведение не определено. То есть: никаких ожиданий относительно того, что может произойти, быть не может.

person littleadv    schedule 21.12.2013

На мой взгляд, это не должно работать [...], но это работает.

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

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

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

person Community    schedule 21.12.2013

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

person Harald    schedule 21.12.2013

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

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

person Imran Ali Khan    schedule 21.12.2013

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

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

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

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

person Anis_Stack    schedule 21.12.2013