2016-03-11 2 views
1

Я пытаюсь использовать sbrk системный вызов, чтобы попросить одну страницу памяти и разделить эту страницу на небольшие блоки, но мой код всегда попадает какой-то недопустимое память:Почему я ударил недопустимую память после sbrk?

void sbrkBlocks() { 
    int *b = sbrk(0); 
    if(sbrk(sysconf(_SC_PAGESIZE)) == (void *)-1) { 
     printf("sbrk failed\n"); 
     return NULL; 
    } 
    void *bound =b + sysconf(_SC_PAGESIZE); 
    while (b + 16 <=bound) { 
     *b = 1; 
     b+= 16; 
    } 
} 

Как если я sbrk(0) на 0x804d000, оценка после sbrk(one_page_size) будет 0x8055000, но код получит ошибку сегментации на 0x804e000.

+0

это для приложения или модуля ядра? –

+0

Это для реализации malloc, я изменил свой фактический код, поэтому было бы легче подталкивать. –

+2

В моей системе 'sysconf (_SC_PAGESIZE)' возвращает 4096, что, я думаю, довольно типично. Если у вас одно и то же, вы ошибочно выполнили свои связанные вычисления: для начального разрыва в '0x804d000' новый разрыв должен быть равен' 0x804e000', где вы получите segfault. –

ответ

5

Вы делаете свою арифметику указателей неправильно. sysconf(_SC_PAGESIZE) возвращает размер в байт страницы. Добавив, что b, который является указателем на int, добавляет к нему sizeof(int) * _SC_PAGESIZE.

Выполнить это:

int *b = sbrk(0); 
printf("b = %p\n", b); 
printf("PAGESIZE = %d\n", sysconf(_SC_PAGESIZE)); 
void *bound = b + sysconf(_SC_PAGESIZE); 
printf("bound = %p\n", bound); 
printf("bound - b = %d\n", (char *) bound - (char *) b); 

Вы должны получить что-то вроде:

b = 0x10c37d000 
PAGESIZE = 4096 
bound = 0x10c37e000 
bound - b = 16384 

Вы просто писать мимо конца границы вы на самом деле выделения.

+0

Большое вам спасибо, вот почему я ударил недопустимую память. –

+2

Добро пожаловать. Вы должны отметить ответ как принятый. – bnaecker

1

Обратите внимание, что на некоторых системах, sbrk не возвращает выровненные указатели и вы должны проверить фактический указатель после вызова sbrk:

#include <stdio.h> 
#include <unistd.h> 

int main(void) { 
    int *l = sbrk(0); 
    sbrk(getpagesize()); 
    int *u = sbrk(0); // do this to get the actual aligned pointer 
    //int *u = l + getpagesize(); // may fail, may not be accurate 
    printf("l=%p, u=%p\n", l, u); 
    while (l + 16 < u) { 
     *l = 1; 
     l += 16; 
     printf("l=%p\n", l); 
    } 
    return 0; 
} 
+2

Если он выполнял неправильную выровненную запись в действительную память - в системе, где это имеет значение, - тогда он не ожидал бы получить ошибку шины вместо ошибки сегментации? –

+1

Спасибо, хотя это не причина моей проблемы, но я добавлю чек, который вы упомянули. –

+0

@JohnBollinger Может быть ... Возможно. Я видел тот же (плохой) код, генерирующий 'SIGBUS' и' SIGSEGV' в зависимости от того, на какой машине он работал. – bishop

 Смежные вопросы

  • Нет связанных вопросов^_^