首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >由mmap()分配的内存空间如何防止被“新”调用分配?

由mmap()分配的内存空间如何防止被“新”调用分配?
EN

Stack Overflow用户
提问于 2015-03-11 10:40:56
回答 4查看 916关注 0票数 0

我在一个特定的地址分配空间

mmap(...,PROT_WRITE | PROT_READ, MAP_PRIVATE | MAP_ANONYMOUS | MAP_FIXED,...)

但是,如果我调用类似于new char[large_number]的东西,则会创建数组,重叠以前分配的内存段。所以我的问题是,我应该做些什么来保护我之前尝试分配的内存段。

编辑:对于以下代码,

代码语言:javascript
运行
复制
char* base_address = (char*)malloc(sizeof(long));
int page_size = getpagesize();
size_t length = page_size;
char* selected_address = (char*)base_address + (page_size - ((long)base_address % page_size));

char* allocated_address = (char*) mmap(selected_address, page_size * 4, PROT_WRITE | PROT_READ
    ,  MAP_SHARED | MAP_ANONYMOUS | MAP_FIXED, -1, 0);

int* a = new int[page_size / 4];
// mprotect(allocated_address, page_size * 4, PROT_READ | PROT_WRITE);
int* b = new (allocated_address) int[page_size / 2];
int* c = new (allocated_address + page_size / 2 ) int[page_size/2];

int* d = (int*)malloc(page_size);

cout << "base_address:" << (int*)base_address << " selected_address:" << (int*)selected_address << " allocated_address:" << (int*)allocated_address << endl;
cout << "a=" << a << " end=" << &a[page_size/4 - 1] << endl;
cout << "b=" << b << " end=" << &b[page_size/2 - 1] << endl;
cout << "c=" << c << " end=" << &c[page_size/2 - 1] << endl;
cout << "d=" << d << " end=" << &d[page_size - 1] << endl;

我得到了

代码语言:javascript
运行
复制
base_address:0x603010 selected_address:0x604000 allocated_address:0x604000
a=0x603030 end=0x60402c
b=0x604000 end=0x605ffc
c=0x604800 end=0x6067fc
d=0x604040 end=0x60803c

不应该在mmap分配的空间之外分配a和d段吗?

EN

回答 4

Stack Overflow用户

回答已采纳

发布于 2015-03-11 11:10:55

来自mmap在我的系统上的手册页(OS X)

如果在标志中指定了MAP_FIXED,系统将尝试将映射放置在指定的地址,可能会删除该位置已经存在的映射。

您正在强迫mmap()在上面的第一页映射malloc()交给您的地址。很可能,new调用malloc()来获取内存块,而且内存分配程序可能认为它拥有要映射到的页面。您不会告诉分配器它不能使用该页面,所以它继续并执行它。

MAP_FIXED. 不指定只需使用它返回给您的地址,而不需要指定MAP_FIXED

票数 2
EN

Stack Overflow用户

发布于 2015-03-11 10:53:36

mmap(...,PROT_WRITE | PROT_READ, MAP_SHARED | MAP_ANONYMOUS | MAP_FIXED,...)

内存映射只能是MAP_SHAREDMAP_ANONYMOUS,但不能两者兼而有之。

但是,如果我调用类似于new char[large_number]的东西,则会创建数组,重叠以前分配的内存段。

这是不可能的忽略mmap调用的返回值,调用很可能失败。

票数 2
EN

Stack Overflow用户

发布于 2015-03-11 11:13:49

您的实现平台可能通过跟踪堆使用的最高页面地址来隐式地增长堆,然后在需要时简单地增加它。第一次访问以前未使用的页面会生成一个页面错误,然后O/S会自动增加进程的虚拟内存地址空间,从错误地址开始。

在Linux上,有关此过程的更完整描述,请参见sbrk(2)手册页。

因此,这里发生的事情是,您显式地将mmap()请求到C库将使用的地址,作为分配的内存。C库很高兴地增加了数据段,侵入了您的mmap编辑空间。

这是一个简单的例子“医生,当我像这样挥动我的手臂时会很疼”;“好吧,不要这样挥动你的手臂。”

Linux上的mmap()手册页对mmap()的第一个参数提供了警告:

如果addr为NULL,那么内核将选择创建映射的地址;这是创建新的map-ping的最可移植的方法。

空地址导致内核将您的新内存段映射到一个地址,该地址与任何其他地址都没有,也没有接近进程的数据段,这两个地址不会相互干扰。

如果像在您的示例中一样,在虚拟地址空间中显式地使用mmap()作为一个特定的地址,那么您就有责任避免遇到麻烦,并且确切地知道流程中发生了什么,包括C库正在做什么。

我还应该指出,为了计算新的mmaped地址,您正在计算一个指针地址,该指针地址位于当前分配数组的末尾。

严格来说,这是未定义的行为。在这一点上,只要严格的C/C++遵从性,所有的赌注都会被取消。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/28984388

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档