我在一个特定的地址分配空间
mmap(...,PROT_WRITE | PROT_READ, MAP_PRIVATE | MAP_ANONYMOUS | MAP_FIXED,...)
但是,如果我调用类似于new char[large_number]
的东西,则会创建数组,重叠以前分配的内存段。所以我的问题是,我应该做些什么来保护我之前尝试分配的内存段。
编辑:对于以下代码,
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;
我得到了
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段吗?
发布于 2015-03-11 11:10:55
来自mmap在我的系统上的手册页(OS X)
如果在标志中指定了MAP_FIXED,系统将尝试将映射放置在指定的地址,可能会删除该位置已经存在的映射。
您正在强迫mmap()
在上面的第一页映射malloc()
交给您的地址。很可能,new
调用malloc()
来获取内存块,而且内存分配程序可能认为它拥有要映射到的页面。您不会告诉分配器它不能使用该页面,所以它继续并执行它。
MAP_FIXED
. 不指定只需使用它返回给您的地址,而不需要指定MAP_FIXED
。
发布于 2015-03-11 10:53:36
mmap(...,PROT_WRITE | PROT_READ, MAP_SHARED | MAP_ANONYMOUS | MAP_FIXED,...)
内存映射只能是MAP_SHARED
或MAP_ANONYMOUS
,但不能两者兼而有之。
但是,如果我调用类似于
new char[large_number]
的东西,则会创建数组,重叠以前分配的内存段。
这是不可能的忽略mmap
调用的返回值,调用很可能失败。
发布于 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++遵从性,所有的赌注都会被取消。
https://stackoverflow.com/questions/28984388
复制相似问题