2010-10-06 140 views
12

我試圖保持學生的代碼不會與分配一起運行,並拖動我的測試機器停下來。我試過如何限制使用malloc()獲取的內存而不限制堆棧?

setrlimit(RLIMIT_DATA, r); 

其中r是一個結構體,它持有極限。但不幸的是,雖然這個限制從分配停止brksbrk,C庫只是故障轉移到mmap和保持正常分配。

我也試過

setrlimit(RLIMIT_AS, r) 

,這將停止在其軌道的過程中,但這一補救措施過於嚴厲—這是不可能的過程,從ENOMEM錯誤中恢復,因爲沒有爲沒有堆棧空間代碼在遇到從malloc()返回的NULL值時所進行的調用。

我有過二進制有限控制,所以如果可能的話用系統調用來完成,我會更喜歡。但我需要一些限制分配的方法,而不會破壞進程恢復的能力。有沒有人有建議?

更新:我發現一些所謂的failmalloc,但它是不是很複雜,雖然我可能會導致失敗有了它,我總是得到一個segfault是GDB不能診斷。

進一步更新:我發現setrlimit(RLIMIT_AS, r)確實似乎做我想要的工作,至少在某些情況下—的內存設計缺陷是發生了後來被故障無關的模塊中造成的。除非有人提出了一些有趣的事情(或者保留問題的理由),否則我可能會刪除該問題。

+0

如果你只是想阻止濫用/ bug的程序取消系統,不要費心讓他們從失敗的'malloc'中恢復。讓操作系統殺死它們並完成它。無論如何,一個正確的程序大概不應該達到極限。 – 2010-10-06 05:49:40

+0

許多學生提交不正確的課程。如果他們轉儲核心,他們會得到零。如果他們恢復並中止,則獲得部分信用。 – 2010-10-07 05:32:02

回答

3

你可以強制在不知情的學生的宏? :-)

#define malloc(bytes) limited_malloc(bytes) 

,也爲limited_malloc限制什麼可以做一個定義。由failmalloc使用的想法

4

大廈,您可以使用LD_PRELOAD* 環境變量和函數介入到周圍malloc()構建一個包裝和施加任何限制存在。

您將需要使用dlsym()指針動態加載到原來的malloc()。您不能直接從包裝器中調用原始malloc(),因爲它將被解釋爲對包裝器本身的遞歸調用。

#define _GNU_SOURCE 
#include <stdio.h> 
#include <stdint.h> 
#include <dlfcn.h> 

void * malloc(size_t size) 
{ 
    static void * (*func)(size_t) = NULL; 
    void * ret; 

    if (!func) 
    { 
     /* get reference to original (libc provided) malloc */ 
     func = (void *(*)(size_t)) dlsym(RTLD_NEXT, "malloc"); 
    } 

    /* impose any necessary restrictions before calling malloc */ 
    ... 

    /* call original malloc */ 
    ret = func(size); 

    /* impose any necessary restrictions after calling malloc */ 
    ... 

    return ret; 
}

*注:LD_PRELOAD必須指定完整路徑中介庫,並且該庫介入是setuid程序禁用,以避免安全問題。


alternative使用dlsym()是使用GNU鏈接--wrap symbol選項。

+1

我想,valgrind的來源應該包含類似於這種方法的東西。 – 2010-10-06 07:14:26