2009-11-06 132 views
3

在我使用mprotect()保护内存区域后,第一次调用malloc()时出现了分段错误。这是一个代码sniplet,做内存分配的保护:malloc导致mprotect出现分段错误

#define PAGESIZE 4096 
void* paalloc(int size){ // Allocates and aligns memory 
     int type_size = sizeof(double); 
     void* p; 
     p = malloc(type_size*size+PAGESIZE-1); 
     p = (void*)(((long) p + PAGESIZE-1) & ~(PAGESIZE-1)); 
     return p; 
} 
void aprotect(int size, void* array){ // Protects memory after values are set 
     int type_size = sizeof(double); 
     if (mprotect(array, type_size*size, PROT_READ)) { 
       perror("Couldn't mprotect"); 
     } 
} 

我想用mprotect的避免任何写入我的数组(这是预先计算正弦/余弦值)。这是一个愚蠢的想法吗?

+0

请同时添加类型cast(void *)mallac .... – Vijay 2009-11-06 12:59:56

+0

@john:您不需要转换 – Wernsey 2009-11-06 13:03:20

+0

没有足够的关联来编辑帖子,但是那些发现这个问题的人可能也会对这:http://stackoverflow.com/questions/1686464/alternatives-to-mprotect咖啡的关于页面对齐的答案已经死了,似乎今天是一个热门话题:) – 2009-11-06 13:32:32

回答

7

mprotect只能以页面为单位工作,因为您可能已经知道了。在这种情况下,您需要将块的起始位置与页面边界正确对齐,但是而不是所做的是确保将您的分配延伸至您要在其中使用的最后一页的末尾。

这意味着您的mprotect正在保护您的分配结束后的数据(该页的末尾),这是下一个malloc调用假定可以写入的空间。

最简单的修复方法是将malloc调用中的PAGE_SIZE - 1更改为PAGE_SIZE * 2

+0

谢谢!我是否错过了某些内容或在mprotect的手册页中是否有错误?这个例子有同样的问题... – hanno 2009-11-06 13:32:44

+0

我怀疑你的'mprotect'手册页与我的不同,它使用'memalign'来分配一个页面对齐的,页面多个大小的内存块而不是'malloc'。 (你应该考虑使用'memalign',实际上)。 – caf 2009-11-06 13:40:45

0

caf已经确定问题的原因。

我认为你可以不mprotect()做:如果你声明的指针静止在它是重要的lookup.c(或任何它被称为),然后有一个非静态double get_sine(int index);功能。这样,lookup.c以外的代码只能调用get_sine(),而不能直接访问表。

而且,从我mprotect()手册页:

POSIX说的mprotect()只能从mmap获取 (2)

的内存区域中使用 (显然,这不不适用于Linux。您使用哪种操作系统?)

1

我建议你直接使用mmap创建一个匿名映射,然后在完成写入数组之后调用mprotect。由于您始终分配整个页面,因此根本无法使用堆。它的主要目的是处理小(ish)对象的分配和释放。处理页面块时,只会增加不必要的开销。