2009-11-06 159 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)對象的分配和釋放。處理頁面塊時,只會增加不必要的開銷。