c - 使用 mmap 和 memset 在 C 中分配内存

标签 c memory segmentation-fault heap-memory 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 }

最佳答案

您第一次尝试p6像预期的那样失败,但作为副作用,您仍然更新全局 memused在第 32 行,在第 35 行保释之前。

因此,下一次尝试 p6也在第 35 行保留。(所有行号都与顶部源列表相关。)

如果您查看第二次尝试的检查 p6 (底部列表中的第 64 行)p6NULL再次; NULL % 16 == 0 ,所以我们不输入if陈述。这意味着我们会陷入 memset ,其目的地是 NULL指针。 (因此SIGSEGV。)

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

关于c - 使用 mmap 和 memset 在 C 中分配内存,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49247339/

相关文章:

复合文字和清理

tomcat - 是否有可能像 Tomcat Manager 那样使用 JMX 获取可用/总计/最大内存?

java - 内存不足且 CPU 消耗低

c - C 是否为函数开始时 undefined variable 分配内存?

cmake 忽略 -D CMAKE_BUILD_TYPE=Debug

c++ - 可互换声明的变量具有相同的内存地址模式

c - 将结构插入队列时出现段错误

c - 如何为可变数量的单词标记化输入

c++ - 我如何在框架中找到 argc 的地址?

c - 如何检查打开的文件是处于读取模式还是写入模式?