У меня есть следующее задание для онлайн-класса, и мне было интересно, знаком ли кто-нибудь с параноидальными массивами, так как очень трудно получить помощь для этого конкретного класса.
Ваш массив paranoid предоставит очень простой интерфейс, предоставленный в parray.h. Вы можете
Предположим, что parray не будет бесплатным. При вызове parray new создается массив с номером набора
записей (аргумент count) фиксированного размера (аргумент size). Внутренне, парри будет
не размещать элементы последовательно в памяти, поэтому функция ввода parray возвращает
указатель на данную запись (указывается индексом аргумента).
Чтобы вызвать segfault при переполнении внутри элемента, вы должны использовать guard
страницы. Основная цель защитной страницы - запускать ошибки при обращении к ним. Таким образом, разрешения на чтение, запись и выполнение для таблицы защиты таблиц отключены, поэтому любой доступ к
страница вызовет ошибку. Когда защитная страница размещается сразу после буфера или
структура данных, любые ошибки переполнения буфера, затрагивающие этот фрагмент памяти, будут поражать
страница, активирующая мгновенный сегмент
Каждая запись в вашем массиве должна быть ограничена защитными страницами с каждой стороны. Например,
массив с 10 записями должен использовать 11 защитных страниц: одну перед первой записью, одну после
последняя запись и девять между последовательными записями.
Мой вызов parray_new и parray_entry выглядит следующим образом:
typedef char byte;
parray_t* parray_new(int size, int count)
{
struct parray* p = NULL;
// TODO: Allocate and return parray
// Add guard pages first at this time
int pagesize = getpagesize();
p->size = (size * count) + (pagesize * count) + pagesize;
p->array = malloc(p->size + pagesize - 1);
if(posix_memalign(&p->array, p->size, count))
{
exit(0);
}
return p;
}
void* parray_entry(struct parray* p, int index)
{
//int pagesize = getpagesize();
byte* entry = NULL;
// TODO: compute correct entry
if (mprotect(&p->array, p->size-1, PROT_READ))
{
exit(0);
}
if (mprotect(&p->array, p->size, PROT_WRITE))
{
exit(0);
}
entry = (void*)(p->array + index);
return entry;
}
У меня также есть следующий обработчик:
static void handler(int sig, siginfo_t *si, void* unused)
{
// TODO: Use fprintf or perror to print
// a message indicating a segmentation fault
// happened and provide the memory address
// where the fault happened
fprintf(stderr, "Segmentation Fault\n k = %d, %p\n", sig, si >si_addr);
}
Наконец, основной метод:
int main(void)
{
struct sigaction sa;
/*
* TODO: Overwrite the signal handler for
* SIGSEGV
*/
memset(&sa, '\0', sizeof(sa));
sa.sa_flags = SA_SIGINFO;
sa.sa_sigaction = handler;
if (sigaction(SIGSEGV, &sa, NULL) == -1)
{
perror("sigaction");
exit(EXIT_FAILURE);
}
}
Есть также несколько тестов для запуска в основном методе, но я их пропустил, потому что я сталкиваюсь с ошибкой еще до того, как достигну их. Что происходит, обработчик печатает вечно (ошибка сегментации, k = 11, 0x8). Я не знаю значения 11 или 0x8, но это не останавливает печать этой последовательности, пока я не заставлю ее.
Любая помощь будет принята с благодарностью, и я прошу прощения за длину этого поста. Спасибо
Редактировать: из того, что я вижу, обработчик продолжает печатать. Это не так сильно, что я получаю ошибку сегмента (я мог бы быть), но все, что я помещаю в обработчик, оно продолжает печатать. Кроме того, если я изменю его на perror, он сделает то же самое. Что я могу сделать, чтобы программа продолжила работу после обработчика?