使用MREMAP_FIXED调用mremap映射到现有地址范围时报Bad address错误
错误成因
核心问题出在remap_impl2的mremap调用参数不符合预期,导致虚拟内存区域(VMA)结构和你记录的memoryCapacity不匹配:
- 先明确
mremap的参数定义:
void *mremap(void *old_address, size_t old_size, size_t new_size, int flags, void *new_address);
第三个参数new_size是重映射后新内存段的大小,而你在代码里传的是和old_size一样的memoryCapacity,也就是重映射后的段大小和原来的完全一样,没有完成扩容逻辑。
2. 第一次扩容(i=2)时的隐式问题:
- 你先
mmap了8KB的连续虚拟地址空间,得到地址0x7f72b4718000,这是一个连续的VMA。 - 调用
mremap把原来4KB的段移动到这个新地址,因为new_size传的是4KB,所以内核只会把新地址开头的4KB替换为原来的内存段,剩余的4KB还是原来mmap出来的独立VMA,和前4KB不属于同一段连续映射。 - 你把
memoryCapacity更新为8KB,但实际上rawtotaldata指向的连续VMA只有4KB,后面的4KB属于另一个不相关的VMA。
- 第二次扩容(i=3)时报错的直接原因:
- 调用
mremap时传入的old_size是你记录的8KB,但内核查询到rawtotaldata开头的连续VMA只有4KB,找不到长度为8KB的连续映射段,因此返回EFAULT错误,对应你看到的"Bad address"提示。
修复方案
把remap_impl2里mremap的第三个参数改为你要扩容的目标大小newcapacity即可,mremap会自动帮你扩展到目标大小,得到连续的虚拟地址段:
void* remapped = mremap(rawtotaldata, memoryCapacity, newcapacity, MREMAP_MAYMOVE | MREMAP_FIXED, newptr);
修改后重映射得到的就是连续的newcapacity长度的VMA,和你记录的memoryCapacity完全匹配,后续扩容就不会触发地址错误。
内容的提问来源于stack exchange,提问作者Abator Abetor
相关产品推荐
相关产品推荐

