我在vmware 11.0和linux-2.6.34上遇到了这个问题,gcc 4.9.2,没有在真实硬件上测试过。 代码运行成功后,打印的消息没有SIGSEGV。但如果我在munmap之前取消注释printf,就会发现一个SIGSEGV。
在munmap()之前和之后的地图打印在以下消息中。
static void check_mmap(void){
int fd, i;
char *p = NULL;
if ((fd = shm_open("xxxxxxxxxxxx", O_RDWR|O_CREAT|O_TRUNC, 0666)) == -1) {
printf("open shm file failed.\n");
return;
}
if (ftruncate(fd, 4096) == -1)
goto out;
p = mmap(NULL, 4096, PROT_READ | PROT_WRITE, MAP_PRIVATE, fd, 0);
if (MAP_FAILED == p)
goto out;
//printf("Mapped at %p\n", p);
getchar(); // <----- chance to print maps befor munmap
if (munmap(p, 4096) != 0)
printf("munmap error: %s\n", strerror(errno));
printf("Corrupting mmap memory.\n");
for(i = 0; i < 4095; i ++)
p[i] = 0;
printf("Done\n");
getchar(); // <----- chance to print maps after munmap
out:
close(fd);
if (p)
munmap(p, 4096);
}
在munmap之前映射,shm xxxxxxxxxxxx在7f3f2683a000-7f3f2683b000进行映射
00400000-00401000 r-xp 00000000 00:14 121 / mnt / hgfs / vm_shared / asan / asan1
00600000-00601000 rw-p 00000000 00:14 121 / mnt / hgfs / vm_shared / asan / asan1
7f3f25ea6000-7f3f25ebd000 r-xp 00000000 08:02 347266 /lib64/libpthread-2.11.3.so
7f3f25ebd000-7f3f260bc000 --- p 00017000 08:02 347266 /lib64/libpthread-2.11.3.so
7f3f260bc000-7f3f260bd000 r - p 00016000 08:02 347266 /lib64/libpthread-2.11.3.so
7f3f260bd000-7f3f260be000 rw-p 00017000 08:02 347266 /lib64/libpthread-2.11.3.so
7f3f260be000-7f3f260c2000 rw-p 00000000 00:00 0
7f3f260c2000-7f3f2620e000 r-xp 00000000 08:02 298091 /lib64/libc-2.11.1.so
7f3f2620e000-7f3f2640d000 --- p 0014c000 08:02 298091 /lib64/libc-2.11.1.so
7f3f2640d000-7f3f26411000 r - p 0014b000 08:02 298091 /lib64/libc-2.11.1.so
7f3f26411000-7f3f26412000 rw-p 0014f000 08:02 298091 /lib64/libc-2.11.1.so
7f3f26412000-7f3f26417000 rw-p 00000000 00:00 0
7f3f26417000-7f3f2641e000 r-xp 00000000 08:02 335978 /lib64/librt-2.11.1.so
7f3f2641e000-7f3f2661d000 --- p 00007000 08:02 335978 /lib64/librt-2.11.1.so
7f3f2661d000-7f3f2661e000 r - p 00006000 08:02 335978 /lib64/librt-2.11.1.so
7f3f2661e000-7f3f2661f000 rw-p 00007000 08:02 335978 /lib64/librt-2.11.1.so
7f3f2661f000-7f3f2663d000 r-xp 00000000 08:02 260202 /lib64/ld-2.11.1.so
7f3f2682b000-7f3f2682e000 rw-p 00000000 00:00 0
7f3f26839000-7f3f2683a000 rw-p 00000000 00:00 0
7f3f2683a000-7f3f2683b000 rw-p 00000000 00:11 16078 / dev / shm / xxxxxxxxxxxx
7f3f2683b000-7f3f2683c000 rw-p 00000000 00:00 0
7f3f2683c000-7f3f2683d000 r - p 0001d000 08:02 260202 /lib64/ld-2.11.1.so
7f3f2683d000-7f3f2683e000 rw-p 0001e000 08:02 260202 /lib64/ld-2.11.1.so
7f3f2683e000-7f3f2683f000 rw-p 00000000 00:00 0
7fffd9ce3000-7fffd9d04000 rw-p 00000000 00:00 0 [stack]
7fffd9dff000-7fffd9e00000 r-xp 00000000 00:00 0 [vdso]
ffffffffff600000-ffffffffff601000 r-xp 00000000 00:00 0 [vsyscall]
在munmap之后映射,shm已成功取消映射。
00400000-00401000 r-xp 00000000 00:14 121 / mnt / hgfs / vm_shared / asan / asan1
00600000-00601000 rw-p 00000000 00:14 121 / mnt / hgfs / vm_shared / asan / asan1
7f3f25ea6000-7f3f25ebd000 r-xp 00000000 08:02 347266 /lib64/libpthread-2.11.3.so
7f3f25ebd000-7f3f260bc000 --- p 00017000 08:02 347266 /lib64/libpthread-2.11.3.so
7f3f260bc000-7f3f260bd000 r - p 00016000 08:02 347266 /lib64/libpthread-2.11.3.so
7f3f260bd000-7f3f260be000 rw-p 00017000 08:02 347266 /lib64/libpthread-2.11.3.so
7f3f260be000-7f3f260c2000 rw-p 00000000 00:00 0
7f3f260c2000-7f3f2620e000 r-xp 00000000 08:02 298091 /lib64/libc-2.11.1.so
7f3f2620e000-7f3f2640d000 --- p 0014c000 08:02 298091 /lib64/libc-2.11.1.so
7f3f2640d000-7f3f26411000 r - p 0014b000 08:02 298091 /lib64/libc-2.11.1.so
7f3f26411000-7f3f26412000 rw-p 0014f000 08:02 298091 /lib64/libc-2.11.1.so
7f3f26412000-7f3f26417000 rw-p 00000000 00:00 0
7f3f26417000-7f3f2641e000 r-xp 00000000 08:02 335978 /lib64/librt-2.11.1.so
7f3f2641e000-7f3f2661d000 --- p 00007000 08:02 335978 /lib64/librt-2.11.1.so
7f3f2661d000-7f3f2661e000 r - p 00006000 08:02 335978 /lib64/librt-2.11.1.so
7f3f2661e000-7f3f2661f000 rw-p 00007000 08:02 335978 /lib64/librt-2.11.1.so
7f3f2661f000-7f3f2663d000 r-xp 00000000 08:02 260202 /lib64/ld-2.11.1.so
7f3f2682b000-7f3f2682e000 rw-p 00000000 00:00 0
7f3f26839000-7f3f2683b000 rw-p 00000000 00:00 0
7f3f2683b000-7f3f2683c000 rw-p 00000000 00:00 0
7f3f2683c000-7f3f2683d000 r - p 0001d000 08:02 260202 /lib64/ld-2.11.1.so
7f3f2683d000-7f3f2683e000 rw-p 0001e000 08:02 260202 /lib64/ld-2.11.1.so
7f3f2683e000-7f3f2683f000 rw-p 00000000 00:00 0
7fffd9ce3000-7fffd9d04000 rw-p 00000000 00:00 0 [stack]
7fffd9dff000-7fffd9e00000 r-xp 00000000 00:00 0 [vdso]
ffffffffff600000-ffffffffff601000 r-xp 00000000 00:00 0 [vsyscall]
以下是objdump
0000000000400890 <main>:
400890: 55 push %rbp
400891: 53 push %rbx
400892: ba b6 01 00 00 mov $0x1b6,%edx
400897: be 42 02 00 00 mov $0x242,%esi
40089c: bf 9c 0a 40 00 mov $0x400a9c,%edi
4008a1: 48 83 ec 08 sub $0x8,%rsp
4008a5: e8 fe fd ff ff callq 4006a8 <shm_open@plt>
4008aa: 83 f8 ff cmp $0xffffffffffffffff,%eax
4008ad: 89 c3 mov %eax,%ebx
4008af: 0f 84 c0 00 00 00 je 400975 <main+0xe5>
4008b5: be 00 10 00 00 mov $0x1000,%esi
4008ba: 89 c7 mov %eax,%edi
4008bc: e8 37 fe ff ff callq 4006f8 <ftruncate@plt>
4008c1: 83 f8 ff cmp $0xffffffffffffffff,%eax
4008c4: 0f 84 9b 00 00 00 je 400965 <main+0xd5>
4008ca: 45 31 c9 xor %r9d,%r9d
4008cd: 31 ff xor %edi,%edi
4008cf: 41 89 d8 mov %ebx,%r8d
4008d2: b9 02 00 00 00 mov $0x2,%ecx
4008d7: ba 03 00 00 00 mov $0x3,%edx
4008dc: be 00 10 00 00 mov $0x1000,%esi
4008e1: e8 22 fe ff ff callq 400708 <mmap@plt>
4008e6: 48 83 f8 ff cmp $0xffffffffffffffff,%rax
4008ea: 48 89 c5 mov %rax,%rbp
4008ed: 0f 84 8e 00 00 00 je 400981 <main+0xf1>
4008f3: 48 8b 3d 0e 05 20 00 mov 0x20050e(%rip),%rdi # 600e08 <__TMC_END__>
4008fa: e8 b9 fd ff ff callq 4006b8 <_IO_getc@plt>
4008ff: be 00 10 00 00 mov $0x1000,%esi
400904: 48 89 ef mov %rbp,%rdi
400907: e8 dc fd ff ff callq 4006e8 <munmap@plt>
40090c: 85 c0 test %eax,%eax
40090e: 75 7a jne 40098a <main+0xfa>
400910: bf d1 0a 40 00 mov $0x400ad1,%edi
400915: e8 6e fd ff ff callq 400688 <puts@plt>
40091a: 48 8d 8d ff 0f 00 00 lea 0xfff(%rbp),%rcx
400921: 48 89 ea mov %rbp,%rdx
400924: 0f 1f 40 00 nopl 0x0(%rax)
400928: c6 02 00 movb $0x0,(%rdx)
40092b: 48 83 c2 01 add $0x1,%rdx
40092f: 48 39 ca cmp %rcx,%rdx
400932: 75 f4 jne 400928 <main+0x98>
400934: bf e9 0a 40 00 mov $0x400ae9,%edi
400939: e8 4a fd ff ff callq 400688 <puts@plt>
40093e: 48 8b 3d c3 04 20 00 mov 0x2004c3(%rip),%rdi # 600e08 <__TMC_END__>
400945: e8 6e fd ff ff callq 4006b8 <_IO_getc@plt>
答案 0 :(得分:0)
您正在调用“未定义的行为”。什么事情都可能发生。你不能抱怨说,在一种情况下,你比其他情况更喜欢结果,而两者都有未定义的行为。只是停止运行无效代码。
答案 1 :(得分:0)
以下代码成功运行并且没有打印消息 SIGSEGV。但是如果我在munmap之前取消注释printf,那么SIGSEGV就是 捕获。
这种表面上令人吃惊的行为有一个简单的解释。访问未映射的Linux内存时,确实需要 Segmentation fault 。只是在没有munmap 之前的 printf的情况下,printf("Corrupting mmap memory.\n")
之后的munmap()
构成了程序首次使用stdout
,并且在第一次使用时,{/ 1}},Linux / GNU C库通过mmap()
分配流缓冲区,从而完全重新映射之前未映射的内存页,因此p[i]
可以无故障地访问新的映射内存。