c - 更改大页分配的大小时由于initialize()函数导致的段错误

标签 c memory-management operating-system segmentation-fault

当我使用要分配大页的内存大小时,即当我定义 LENGTH = 4*1024 时,出现段错误。当我定义4*1024*1024时,没有段错误。造成这种情况的根本原因是什么?

代码如下:

#define _POSIX_C_SOURCE 199309
#define _GNU_SOURCE
#include <sched.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/mman.h>
#include <fcntl.h>
#include <time.h>
#include <string.h>
#include <errno.h>

#define PROTECTION (PROT_READ | PROT_WRITE)
#define LENGTH (4*1024)
//#define LENGTH (4*1024*1024)
#define LINE_SIZE 64
#define ASSOC 16
#define CACHE_SIZE (4*1024*1024)
#define WAY_SIZE (CACHE_SIZE/ASSOC)

#ifndef MAP_HUGETLB
#define MAP_HUGETLB 0x40000
#endif

#define ADDR (void *) (0x0UL)
#define FLAGS (MAP_PRIVATE | MAP_ANONYMOUS | MAP_HUGETLB)

int main (int argc, char *argv[]){
...
  // allocate a buffer with the same size as the LLC using huge pages
  buf = mmap(ADDR, LENGTH, PROTECTION, FLAGS, 0, 0);
  if (buf == MAP_FAILED) {
    perror("mmap");
    exit(1);
  }
  set_S = atoi(argv[1]);
  set_M = atoi(argv[2]);
  printf("test 0\n");
  initialize(set_S);
  printf("test 1\n");
  initialize(set_M);
  printf("test 2\n");
  head_S = &buf[set_S*LINE_SIZE];
  printf("test 3\n");
  head_M = &buf[set_M*LINE_SIZE];

...
}

请注意,我的计算机默认没有启用大页面,因此我以 root 身份将其打开:

echo 20 > /proc/sys/vm/nr_hugepages

这是我打开大页面后/proc/meminfo中的大页面相关信息:

HugePages_Total:      20
HugePages_Free:       20
HugePages_Rsvd:        0
HugePages_Surp:        0
Hugepagesize:       2048 kB

程序输出:

$./a.out 1 1
test 0
Segmentation fault (core dumped)

$uname 输出:

Linux mymachine 3.13.0-43-generic #72-Ubuntu SMP Mon Dec 8 19:35:06 UTC 2014 x86_64 x86_64 x86_64 GNU/Linux

编辑1:添加初始化函数:

void initialize(int set){
  int j, k;
  char ** ptr1, ** ptr2;
  char * tmp;

  // re-initialize pointer array of size "size"
  // implementation of Sattolo's random cyclic permutation
  for (j=0; j<ASSOC; j++){
    ptr1 = (char **)&buf[set*LINE_SIZE+j*WAY_SIZE];
    *ptr1 = (char*)ptr1;
  }

  // permute each set
  for (j=ASSOC-1; j>=1; j--){
    k = rand()%j;
    ptr1 = (char **)&buf[set*LINE_SIZE+j*WAY_SIZE];
    ptr2 = (char **)&buf[set*LINE_SIZE+k*WAY_SIZE];
    tmp = *ptr1;
    *ptr1 = *ptr2;
    *ptr2 = tmp;
  }
}

最佳答案

访问大于 mmap 长度的 set*LINE_SIZE+(ASSOC-1)*WAY_SIZE = set*64 + CACHE_SIZE - WAY_SIZE = set*64 + 4*1024*1024 - WAY_SIZELENGTH = 4*1024initialize 循环中,您正在越界访问内存。这就是定义 LENGTH = 4*1024 时出现段错误的原因。

关于c - 更改大页分配的大小时由于initialize()函数导致的段错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27707319/

相关文章:

c - 如何知道新创建的文件的完整路径?

java - JVM 如何为对象分配内存,尽管它们以后可能会增长

operating-system - 饥饿和死锁(操作系统)

java - 可以重新安排被阻塞的线程来做其他工作吗?

linux - 为什么我的进程需要很长时间才能终止?

c - 允许用户在文件中搜索单词的程序

c - 将指向结构的指针的值获取到另一个指向结构的指针

c - 哪个更可能浪费更少的内存,一个大内存管理器还是几个小内存管理器?

c - fork 新进程后线程ID是否改变?

c# - 委托(delegate)分配是否在 C# 中创建新副本?