我需要一些帮助来理解为什么在运行代码后为什么会出现分段错误,或者当使用的内存超过内存时为什么它不会停止。我一直在尝试做各种事情来查看cp和ip的位置,并且在大多数情况下它们是相同的。我已经根据我们的教授给我们的代码构建了这段代码。我编写的代码的不同版本将给我“ p6应该为NULL,但为地址”。
我只是想真正地理解这一点,我不是在寻找想要为我发布代码的人。
任何帮助或建议,表示赞赏。我已经在此处youtube上搜索过Google,但是还没有找到任何帮助。是的,我知道这很糟糕,所以请不要粗鲁,我只是想学习。谢谢。
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,®ion);
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 }
最佳答案
第一次尝试失败了,但是效果是,副作用是,在第35行保释之前,您仍然在第32行更新了全局p6
。
因此,在memused
处的下一次尝试也停留在第35行。(所有行号均相对于顶部源列表)。
如果您查看在p6
处第二次尝试的检查(底部清单的第64行),则p6
再次为p6
; NULL
,因此我们不输入NULL % 16 == 0
语句。这意味着我们进入if
,其目的地是memset
指针。 (因此NULL
。)
您在顶部列表中第33行进行的检查可能应该在第31行之后进行,并且应该在不影响全局状态的情况下进行。即SIGSEGV
。然后,只有在您决定不提早纾困时,才应更新if (mem < (memused + num_bytes_to_allocate))
。