malloc在mprotect后导致分段错误

malloc在mprotect后导致分段错误,c,memory-management,malloc,posix,C,Memory Management,Malloc,Posix,在使用mprotect()保护内存区域后,我第一次调用malloc()时遇到了分段错误。这是一个执行内存分配和保护的代码剪: #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);

在使用mprotect()保护内存区域后,我第一次调用malloc()时遇到了分段错误。这是一个执行内存分配和保护的代码剪:

#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来避免任何写入数组的内容(这些数组是预先计算的正弦/余弦值)。这是一个愚蠢的想法吗?

caf已经确定了问题的原因

我认为您可以不使用
mprotect()
:如果您在
lookup.c
(或其名称)中将指针声明为静态,然后使用非静态的
双get\u sine(int index)非常重要函数。这样,
lookup.c
之外的代码只能调用
get\u sine()
,而不能直接访问表

另外,从我的
mprotect()
手册页:

POSIX说可以使用mprotect() 仅在获得的内存区域上 来自mmap(2)


(显然这不适用于Linux。您使用的是哪种操作系统?

mprotect
只能以页面为单位工作,您可能已经知道了。在本例中,您正确地将块的开头与页面边界对齐,但您没有做的是确保分配扩展到要在其中使用的最后一个页面的结尾

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


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

我建议您直接使用mmap创建匿名映射,然后在完成对数组的写入后调用mprotect。因为您总是分配整个页面,所以使用堆毫无意义。它的主要目的是处理小型(ish)对象的分配和解除分配。当处理页面块时,这只会增加不必要的开销。

请同时添加类型转换(void*)mallac…@john:你不需要相关的转换,因为我无法编辑文章,但是那些发现这个问题的人可能也对此感兴趣:Caf关于页面对齐的答案已经过时了,似乎是今天的热门话题:)谢谢!mprotect手册页中是否有遗漏或错误?这个例子也有同样的问题……我怀疑您的
mprotect
手册页与我的不同,我的手册页使用
memalign
来分配一个页面对齐、页面大小为多个大小的内存块,而不是
malloc
。(实际上,应该考虑使用<代码> MeMalEng/<代码>。