Страницы

Поиск по вопросам

вторник, 24 декабря 2019 г.

Почему следующий код не приводит к сегфолту?

#c #указатели #malloc


#include 

int main() {
    int i = 0;
    unsigned char (*b)[5];

    b = malloc( 5 );

    for ( ; i < 100 ; i++ ) {

        *(b+i)[0] = 192;
        *(b+i)[1] = 168;
        *(b+i)[2] = 0;
        *(b+i)[3] = 1+i;

        printf( "%d.%d.%d.%d\n", *(b+i)[0], *(b+i)[1], *(b+i)[2], *(b+i)[3] );
    }

    return 0;
}


В моем понимании функция malloc() выделяет только 5 байт , и как минимум на 6-м шаге
цикла ( i == 5 ) указатель должен выйти за рамки отведенной процессу памяти, почему
этого не происходит?

Собираю с помощью gcc version 4.9.2 (Debian 4.9.2-10)
    


Ответы

Ответ 1



Из комментария пользователя @nick_n_a: Потому что размер страницы памяти 4096 байт (по умолчанию, так сказать «квант» памяти), и fail может наступить только если для следущей страницы не сделано allocate. Поэтому даже переходя за грань 4096 fail может быть а может и не быть. Пока программа маленькая такие трюки могут заканчиваться ничем, а при большой программе можно получить глюки, которые очень сложно отловить. Если у вас стоит задача получить seg-fail, то можно пробовать читать/писать с шагом 4096 байт.

Ответ 2



Дело в том, что malloc выделяет память из кучи — заранее выделенного диапазона страниц памяти. В куче лежат вперемешку все выделенные malloc-ом фрагменты, плюс служебные данные самой кучи. Соответственно, когда вы пытаетесь обратиться (прочитать или записать) за пределами выделенного вам диапазона памяти, вы всё ещё остаётесь в диапазоне памяти для кучи (потому падения и не происходит). Однако вы залезаете: либо в область, запрошенную другой частью вашей программы (тогда падение произойдёт при некорректной интерпретации тех данных), либо в служебные структуры (тогда падение произойдёт при очередном запросе/освобождении блока кучи).

Комментариев нет:

Отправить комментарий