我正在开发一个自定义内存分配器,需要在每个分配的块的头部添加一些簿记信息.有几种不同的块类型,簿记信息也不同.例如,对于线程之间共享的块,需要添加引用计数器,对于单线程使用的块,没有这样的需要.对于从内存池中获取的块,需要保留对原始池的引用,因为从免费存储中获取的块没有这样的需要.
所以我希望有一个通用接口来为给定的块布局添加和获取某些数据类型.试验这个想法,我找到了一个类似于std :: tuple的解决方案.然而,与元组不同,我添加到标题的每个类型都将是唯一的.我刚刚开始学习模板元编程和其他复杂的c ++,但添加类型的部分对我来说很简单.
我遇到的问题是std::get通过类型模板函数为元组实现类似于C++ 14的方法.我认为没有必要为此编写太多代码,因为编译器能够在方法调用中匹配正确的基类.首先,我将get方法放入模板生成的布局类中.但是,在这种情况下,编译器无法匹配正确的类.通过将get方法移动到另一个手动添加的类层次结构级别来解决该问题.
下面的代码演示了这个问题.将HAVE_GET_IN_LAYOUT定义为0会产生一个工作解决方案,同时将其定义为1会产生一个破碎的解决方案[至少使用clang ++ 3.5和3.6]
问题是,在这种情况下破坏了什么?
#include <cstddef>
#include <iostream>
#ifndef HAVE_GET_IN_LAYOUT
#define HAVE_GET_IN_LAYOUT 0
#endif
constexpr std::size_t Align(std::size_t size, std::size_t offset) {
return (size < 0x8
? (offset + 0x3) & ~0x3
: (size < 0x10 ? (offset + 0x7) & ~0x7 : (offset + 0xf) & ~0xf));
}
template <std::size_t Start, typename... Ts> struct Layout {
static constexpr std::size_t Size = 0;
static constexpr std::size_t …Run Code Online (Sandbox Code Playgroud) Mac OS X mmap手册页说可以分配超级页面,我收集它与Linux大页面相同.
https://developer.apple.com/library/mac/documentation/Darwin/Reference/ManPages/man2/mmap.2.html
但是,在Mac OS X(Yosemite 10.10.5)上,以下简单测试失败:
#include <stdio.h>
#include <sys/mman.h>
#include <mach/vm_statistics.h>
int
main()
{
void *p = mmap((void *) 0x000200000000, 8 * 1024 * 1024,
PROT_READ | PROT_WRITE,
MAP_ANON | MAP_FIXED | MAP_PRIVATE,
VM_FLAGS_SUPERPAGE_SIZE_2MB, 0);
printf("%p\n", p);
if (p == MAP_FAILED)
perror(NULL);
return 0;
}
Run Code Online (Sandbox Code Playgroud)
输出是:
0xffffffffffffffff
Cannot allocate memory
Run Code Online (Sandbox Code Playgroud)
结果与MAP_FIXED从标志中删除并NULL作为地址参数提供的结果相同.VM_FLAGS_SUPERPAGE_SIZE_2MB用-1预期结果替换结果,即没有错误发生,但显然分配的内存空间使用常规的4k页面.
以这种方式分配超级页面可能会出现什么问题?