malloc在mprotect之后导致分段错误

时间:2009-11-06 12:54:33

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

3 个答案:

答案 0 :(得分:7)

mprotect只能以页面为单位工作,您可能已经知道了。在这种情况下,您正确地将块的开头与页面边界对齐,但您做的是确保您的分配延伸到您要去的最后一页的末尾在其中使用。

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

最简单的解决方法是将PAGE_SIZE - 1来电中的malloc更改为PAGE_SIZE * 2

答案 1 :(得分:1)

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

答案 2 :(得分:0)

caf 导致问题被解决。

我认为你可以在没有mprotect()的情况下做到这一点:如果你在lookup.c(或其他任何名称)中将指针声明为静态那么重要,那么就有一个非静态{ {1}}功能。这样,double get_sine(int index);之外的代码只能调用lookup.c,而不能直接访问该表。

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

  

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

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