我根据'memcpy'手册页编写了这段小代码。我执行了它,但我没有得到任何错误。通常,我应该得到'seg fault',因为我试图将消息复制到小目的地。
char str1[1];
char str2[] = "Big Message";
memcpy(&str1, &str2, strlen(str2));
答案 0 :(得分:8)
Undefined behavior 未定义。什么事情都可能发生。它可以运行,崩溃和燃烧,取出互联网,让汽车撞墙。
答案 1 :(得分:4)
为什么你期望得到“seg fault”?
当您尝试访问受操作系统和/或硬件保护的地址区域时,某些平台上会出现“Seg fault”。在您的情况下,memcpy
没有遇到任何此类区域。
事实上,为了应对这种错误而获得“seg fault”是一种罕见且幸运的事情。大多数情况下,您只需要悄悄地破坏位于相邻内存区域的数据。
答案 2 :(得分:2)
Segfault(感谢@zneak)意味着以虚拟内存不会让你的方式访问内存。在大多数情况下,这是由于尝试取消引用NULL指针。
在这种情况下,您的缓冲区溢出(这意味着未定义的行为,这意味着它可以很好地在您的计算机上运行并崩溃并在另一台计算机上刻录)。
答案 3 :(得分:2)
超越数组的边界是C中未定义的行为。这意味着它是非法的,但是如果/当它发生时,语言不需要特别做任何事情。
换句话说,如果你得到一个段错误,真棒!它更容易调试。但不幸的是,你不一定得到一个。在您的情况下,您只是覆盖相邻的内存。 C没有关于数组边界的运行时信息,因此无法强制执行它们。
在Linux系统上,堆栈被分配为一个大的,连续的读写块(有时是可执行的)内存。除非你写了很多数据来传递堆栈本身的边界,否则你不会得到分段错误。
答案 4 :(得分:2)
如果要检查一些非法内存访问,请使用-fsanitize=address
进行编译(至少需要gcc 4.8并且必须安装libasan)并且您将收到错误报告:
==4926==ERROR: AddressSanitizer: stack-buffer-overflow on address 0x7ffd1f1a4bf1 at pc 0x7f259efeadc4 bp 0x7ffd1f1a4bc0 sp 0x7ffd1f1a4368
WRITE of size 11 at 0x7ffd1f1a4bf1 thread T0
#0 0x7f259efeadc3 in __asan_memcpy (/lib64/libasan.so.2+0x8cdc3)
#1 0x4008c0 in main (/home/m/a.out+0x4008c0)
#2 0x7f259ebbe78f in __libc_start_main (/lib64/libc.so.6+0x2078f)
#3 0x400728 in _start (/home/m/a.out+0x400728)
Address 0x7ffd1f1a4bf1 is located in stack of thread T0 at offset 33 in frame
#0 0x400805 in main (/home/m/a.out+0x400805)
This frame has 2 object(s):
[32, 33) 'str1' <== Memory access at offset 33 overflows this variable
[96, 108) 'str2'
HINT: this may be a false positive if your program uses some custom stack unwind mechanism or swapcontext
(longjmp and C++ exceptions *are* supported)
SUMMARY: AddressSanitizer: stack-buffer-overflow ??:0 __asan_memcpy