分配低内存地址

时间:2018-02-05 20:47:16

标签: c memory-address

为了在极限条件下测试软件,我试图创建一个测试用例,其中提供的用户缓冲区分配在一些非常低的内存地址。非常接近NULL的内容,例如0x1000h

这是一个艰难的创造条件。 实际上,我无法在Linux,BSD,Windows或OS-X上使用malloc()生成它。 我确信这种情况可能发生在其他类型的设备上,但我需要一个可重复的测试用例,可以插入到CI测试套件中。

是否存在具有中等复杂度(和依赖性)的已知方法来生成此类条件?

修改:使用mmap()选择解决方案proposed by Eric Postpischil。请注意,as underlined by R.首先需要降低最低地址限制,可在/proc/sys/vm/mmap_min_addr(在Linux上)读取。

sudo sysctl -w vm.mmap_min_addr="4096"

然后是示例代码:

#include <stdio.h>      /* printf */
#include <sys/mman.h>   /* mmap */

int main(int argc, const char** argv)
{
    void* lowBuff = mmap((void*)(0x1000), 64<<10,
                    PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS,
                   -1, 0);
    printf("lowBuff starts at %p \n", lowBuff);
}

结果:

lowBuff starts at 0x1000

3 个答案:

答案 0 :(得分:3)

在POSIX / Unix系统上,您可以使用mmap在特定页面对齐的地址处请求内存。您可以获得的最低价格取决于您的特定系统和环境。

答案 1 :(得分:0)

你只能在C中分配虚拟内存(据我所知,malloc是Windows上VirtualAlloc的包装),虚拟内存由你的操作系统管理,因此几乎不可能预测你会得到什么地址。 它可能永远不会接近0x00。除非您正在编写自定义内存分配系统,否则您不应该对此进行处理,即使这样,它也不应该关心所提供的地址。

答案 2 :(得分:0)

在Windows上,系统保留内存的最低部分(64KB?)专门用于通过无效指针捕获访问。例如,如果您尝试取消引用空指针(可能带有偏移量),则会触发访问冲突。所以0x1000不在桌面上,因为它在第一个64KB内。

超出该初始范围,您可以尝试使用VirtualAlloc保留和提交内存,指定基址(该参数名为lpAddress)。基址将向下舍入到分配粒度(我认为也是64KB)。如果那个内存可用,那么你已经完成了设置,但可能没有。

LPVOID desired_address = (LPVOID) 0x00010000;
LPVOID actual_address =
    VirtualAlloc(desired_address, desired_size,
                 MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE);
if (actual_address == NULL) {
    // we couldn't get the address we wanted.
} else if (actual_address != desired_address) {
    // something very weird happened
} else {
    // we got the low memory we wanted
}

从历史上看,典型的32位用户进程的可执行代码从0x00400000开始加载,DLL通常开始更高(如0x10000000),因此可能在第二个64KB的块中获得幸运。但是地址空间布局随机化(ASLR)会改变这些默认值,谁知道在你有机会之前其他库会抓到什么奇怪的地址。

所以你可以尝试,但是你必须为使用VirtualAlloc尝试获取低内存的可能性做好准备。