如何分配完整内存页
How to allocate full memory pages
在 C 或 C++ 中,在 Linux 上,我想在系统内存页面大小的整页中分配堆内存。
(目的是我想增加有害缓冲区溢出导致分段错误的可能性。
当我使用数组 new (pointer = new char[size]
) 分配内存时C++其中大小是sysconf(_SC_PAGESIZE)
的倍数,那么分配的内存通常不会是sysconf(_SC_PAGESIZE)
的倍数(虚拟)地址,表明我有一个更大块的子集,这一事实证实了写入指针[size] 和一点点超出(强制缓冲区溢出)通常不会导致分段错误。
我的问题是,我能否以某种方式影响内存分配以给我完整的内存页。
我感兴趣的处理器架构是x86_64又名amd64。操作系统要么是最新的Ubuntu,要么是稳定的CentOS Linux(7.3),后者带有内核3.10和gcc-4.8。
我不在乎解决方案是 C 还是C++,因此我要求在这个问题中保留 C 标签。
1)只是从pointer = new char[size]
切换到pointer = aligned_alloc(sysconf(_SC_PAGESIZE), size)
会导致正确的页面对齐,并且(到目前为止,使用小型测试程序)在超出分配范围时一致地生成分段错误。正如@JohnBollinger在对该问题的第一条评论中指出的那样,仅靠分配方法并不能保证分割错误的产生。这可以通过 2) 修复:
2) 函数 mprotect 的 Linux 手册页包含限制对内存页的访问的完整示例。该示例还为 SIGSEGV 提供了一个信号处理程序,我对它不感兴趣,默认操作(中止)对我来说已经足够了。下面是手册页中的示例部分。请注意,将 mprotect 应用于与 mmap 无关的内存区域是 POSIX 未涵盖的特定于 Linux 的扩展。
例
下面的程序分配四页内存,使第三页 这些页面是只读的,然后执行一个遍历 向上通过分配的区域修改字节。
运行程序时我们可能会看到的一个例子是 以后:
$ ./a.out Start of region: 0x804c000 Got SIGSEGV at address: 0x804e000
程序源
#include <unistd.h> #include <signal.h> #include <stdio.h> #include <malloc.h> #include <stdlib.h> #include <errno.h> #include <sys/mman.h> #define handle_error(msg) do { perror(msg); exit(EXIT_FAILURE); } while (0) static char *buffer; static void handler(int sig, siginfo_t *si, void *unused) { printf("Got SIGSEGV at address: 0x%lxn", (long) si->si_addr); exit(EXIT_FAILURE); } int main(int argc, char *argv[]) { char *p; int pagesize; struct sigaction sa; sa.sa_flags = SA_SIGINFO; sigemptyset(&sa.sa_mask); sa.sa_sigaction = handler; if (sigaction(SIGSEGV, &sa, NULL) == -1) handle_error("sigaction"); pagesize = sysconf(_SC_PAGE_SIZE); if (pagesize == -1) handle_error("sysconf"); /* Allocate a buffer aligned on a page boundary; initial protection is PROT_READ | PROT_WRITE */ buffer = memalign(pagesize, 4 * pagesize); if (buffer == NULL) handle_error("memalign"); printf("Start of region: 0x%lxn", (long) buffer); if (mprotect(buffer + pagesize * 2, pagesize, PROT_READ) == -1) handle_error("mprotect"); for (p = buffer ; ; ) *(p++) = 'a'; printf("Loop completedn"); /* Should never happen */ exit(EXIT_SUCCESS); }
前述引文的出处:
此页面是 Linux 手册页项目 4.04 版的一部分。
项目描述、有关报告 bug 的信息,以及 此页面的最新版本可以在 http://www.kernel.org/doc/man-pages/找到。
- Win32编译器选项和内存分配
- 多个文件的内存分配错误"在抛出 'std :: bad_alloc' what (): std :: bad_alloc 的实例后终止调用" [C++]
- 当需要超过16GB的连续内存时,内存分配失败
- 尝试摆脱任何堆内存分配
- 以下代码执行哪种内存分配(动态或静态)?
- 开放 CV 中的动态内存分配,用于视频处理
- 为什么类和 main() 函数中也有动态内存分配
- 使用 NTAllocateVirtualMemory 和 GetProcAddress 的内存分配问题不起作用
- C++:矢量分配器行为、内存分配和智能指针
- 介于 [固定数组] 和 [带内存分配的指针] 之间的性能
- Linux C++ 中的页面对齐内存分配
- 整数内存分配/释放
- 将内存分配返回值强制转换为 TYPE 数组
- C++程序什么都不做,但瓦尔格林德显示内存分配
- 给定特定内存地址的数组的动态内存分配
- 如何完成内存分配
- 我刚刚了解了C++中的动态内存分配
- 在先前调用 string::find 后添加内存分配和内存集会导致它返回 npos.为什么?
- 对于堆上的页面对齐内存分配是否有任何优化或不同的 API?
- 无法删除布尔动态内存分配