我有以下在线课程的作业,想知道是否有人熟悉偏执数组,因为很难获得这个特定课程的帮助。
您的 paranoid 数组将公开 parray.h 中提供的一个非常简单的接口。你可以假设 parray 不会被释放。parray new 调用创建了一个具有固定大小(size 参数)的一组条目(count 参数)的数组。在内部,数组不会在内存中连续排列元素,因此数组入口函数返回一个指向给定入口的指针(由参数索引指定)。为了在元素内溢出时触发段错误,您应该使用保护页。保护页的主要目的是在访问时触发段错误。因此,对保护表的页表读取、写入和执行权限被禁用,因此任何对该页的访问都会触发故障。当保护页紧跟在缓冲区或数据结构之后时,
数组中的每个条目都应由每一侧的保护页限定。例如,一个有 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);
}
}
在 main 方法中还有几个测试要运行,但我把这些都省略了,因为我在到达它们之前就遇到了错误。发生的情况是,处理程序永远打印(分段错误,k = 11, 0x8)。我不知道 11 或 0x8 的意义,但它不会停止打印该序列,直到我强制它。
任何帮助将不胜感激,对于这篇文章的长度,我深表歉意。谢谢
编辑:据我所知,处理程序继续打印。并不是我遇到了段错误(我可能是),但是无论我在处理程序中放入什么,它都会继续打印。另外,如果我将其更改为 perror 它也会这样做。我该怎么做才能让程序在处理程序之后继续?