使用mmap和memset在C中进行内存分配

时间:2018-03-13 02:23:21

标签: c memory segmentation-fault heap mmap

我需要一些帮助来理解为什么我在运行代码后出现分段错误,或者当内存使用超出内存时它为什么不停止。我一直试图做各种事情,看看cp和ip在哪里,大部分时间他们都是一样的。我已经根据教授给我们的内容建立了这段代码。我写的代码的不同版本会给我" p6应该是NULL,但是地址"。 我真的想要理解这一点,我并不是在寻找任何人为我发布代码。 任何帮助或建议表示赞赏。我在这里搜索了谷歌,youtube,但还没找到任何帮助。是的,我意识到这很糟糕所以请不要粗鲁我只是想学习。感谢。

      1
      2 #include <stdio.h>
      3 #include <string.h>
      4 #include <errno.h>
      5 #include <sys/mman.h>
      6 #include <sys/types.h>
      7 #include <unistd.h>
      8
      9     int mem,memused,i, pgsz, *ip;
     10     unsigned char *cp;
     11     void *region;
     12
     13 void heap_init(int num_pages_for_heap)
     14 {
     15     pgsz = getpagesize();
     16     pgsz*=num_pages_for_heap;
     17      mem=pgsz;
     18     region = mmap(NULL, pgsz, PROT_READ|PROT_WRITE, MAP_ANONYMOUS|MAP_PRIVATE, -1, 0);
     19     if (region == ((void *) -1))
     20     {
     21         perror("mmap");
     22        // return 1;
     23     }
     24
     25 }
     26
     27 void *heap_alloc(int num_bytes_to_allocate)
     28 {
     29  if(num_bytes_to_allocate%16 != 0)
     30   {  num_bytes_to_allocate+=8;}
     31
     32     memused+=num_bytes_to_allocate;
     33 if(mem<memused)
     34 { cp=NULL;
     35   return cp;
     36 }
     37
     38 else{
     39  printf("mem used: %d mem: %d region: %p  %d\n",memused,mem,region,&region);
     40    cp = (unsigned char *)region;
     41    *(cp+num_bytes_to_allocate)='a';
     42
     43     ip = (int *)region;
     44    //printf("ip %p, %d\n",ip, &ip);
     45
     46   // *(ip+num_bytes_to_allocate);  // region+1004
     47   // printf("ip %p, %d\n",ip, &ip);
     48   //  *ip+=(num_bytes_to_allocate);
     49
     50     //printf("ip %p\n",ip);
     51     // cp = (unsigned char *)region;
     52     //*cp+=(num_bytes_to_allocate);
     53     //printf("cp %p, %d\n",cp,&cp);
     54
     55  for (i=999; i < num_bytes_to_allocate; i++)//I dont understand why the prof used 999.
     56     {
     57       *(cp+i);
     58
     59     }
     60     printf("\n");
     61
     62
     63 return cp;
     64 }
     65 }
     66 void heap_free(void *pointer_to_area_to_free)
     67 {
     68  //   return;
     69 }

//使用当前代码的输出:

  mem used: 2000 mem: 8192 region: 0x7f8a62941000  6296176

  mem used: 4000 mem: 8192 region: 0x7f8a62941000  6296176

  mem used: 6000 mem: 8192 region: 0x7f8a62941000  6296176

  mem used: 7008 mem: 8192 region: 0x7f8a62941000  6296176

  mem used: 8016 mem: 8192 region: 0x7f8a62941000  6296176

  Segmentation fault

//这是他给我们的驱动程序:

  1 #include <stdio.h>
  2 #include <stdlib.h>
  3 #include <string.h>
  4
  5 void heap_init(int num_pages_for_heap);
  6 void *heap_alloc(int num_bytes_to_allocate);
  7 void heap_free(void *pointer_to_area_to_free);  // not used in this test
  8
  9 int main(int argc, char *argv[])
 10 {
 11     char *p1, *p2, *p3, *p4, *p5, *p6;
 12
 13     heap_init(2);
 14
 15     p1 = (char *) heap_alloc(2000);
 16     if ((long int)p1 % 16 != 0)
 17     {
 18         printf("p1 bad %p  pmod16 %d\n",p1,((long int)p1)%16);
 19         exit(-1);
 20     }
 21     memset(p1,'X',2000);
 22
 23     p2 = (char *) heap_alloc(2000);
 24     if ((long int)p2 % 16 != 0)
 25     {
 26         printf("p2 bad %p  pmod16 %d\n",p2,((long int)p2)%16);
 27         exit(-1);
 28     }
 29     memset(p2,'X',2000);
 30
 31     p3 = (char *) heap_alloc(2000);
 32     if ((long int)p3 % 16 != 0)
 33     {
 34         printf("p3 bad %p  pmod16 %d\n",p3,((long int)p3)%16);
 35         exit(-1);
 36     }
 37     memset(p3,'X',2000);
 38
 39     p4 = (char *) heap_alloc(1000);
 40     if ((long int)p4 % 16 != 0)
 41     {
 42         printf("p4 bad %p  pmod16 %d\n",p4,((long int)p4)%16);
 43         exit(-1);
 44     }
 45     memset(p4,'X',1000);
 46
 47     p5 = (char *) heap_alloc(1000);
 48     if ((long int)p5 % 16 != 0)
 49     {
 50         printf("p5 bad %p  pmod16 %d\n",p5,((long int)p5)%16);
 51         exit(-1);
 52     }
 53     memset(p5,'X',1000);
 54
 55
 56     p6 = (char *) heap_alloc(1500);  // try 1500 first
 57     if (p6 != NULL)
 58     {
 59         printf("p6 should have been NULL, but is %p\n",p6);
 60         exit(-1);
 61     }
 62
 63     p6 = (char *) heap_alloc(50);   // then just get 50
 64     if ((long int)p6 % 16 != 0)
 65     {
 66         printf("p6 bad %p  pmod16 %d\n",p6,((long int)p6)%16);
 67         exit(-1);
 68     }
 69     memset(p6,'X',50);
 70
 71     printf("DONE\n");
 72
 73     return 0;
 74 }

1 个答案:

答案 0 :(得分:1)

p6的第一次尝试失败了,但是作为副作用,在第35行保释之前,你仍然会在第32行更新全局memused

因此,p6的下一次尝试也会在第35行失败。(所有行号相对于顶部源列表。)

如果您查看p6的第二次尝试检查(底部列表中的第64行)p6再次为NULL; NULL % 16 == 0,因此我们不输入if声明。这意味着我们会转到memset,其目标是NULL指针。 (因此SIGSEGV。)

您在顶部列表第33行所做的检查应该可以在第31行之后完成,并且应该在不影响全局状态的情况下完成。即,if (mem < (memused + num_bytes_to_allocate))。然后memused只有在您决定不提前纾困时才会更新。