【问题标题】:Why I do not get 'overflow error'? [duplicate]为什么我没有收到“溢出错误”? [复制]
【发布时间】:2015-07-31 15:35:01
【问题描述】:

我根据“memcpy”手册页编写了一小段代码。我执行了它,但没有收到任何错误。通常,我应该得到“段错误”,因为我试图将消息复制到小尺寸目标。

char str1[1];
char str2[] = "Big Message";

memcpy(&str1, &str2, strlen(str2));

【问题讨论】:

标签: c++ c


【解决方案1】:

Undefined behavior 未定义。什么事情都可能发生。它可以运行、碰撞和燃烧、断开互联网、将汽车撞穿你的墙。

【讨论】:

  • another interesting link 了解未定义行为的含义
  • 如果编译器检测到未定义的行为。为什么它生成可执行文件而不生成编译错误?
  • 编译器不需要在使用未定义行为时抛出错误。见:stackoverflow.com/questions/4417883/…
  • 因为这就是 UB 的意思。具有有效语法的可编译代码,这将烧毁你周围的一切。
【解决方案2】:

您为什么会收到“seg fault”?

“Seg fault”是在您尝试访问受操作系统和/或硬件保护的地址区域时在某些平台上发生的事情。在您的情况下,您 memcpy 没有遇到任何此类区域。

事实上,在响应此类错误时出现“段错误”是一种罕见且幸运的情况。大多数情况下,您只会悄悄地销毁位于相邻内存区域中的自己的数据。

【讨论】:

    【解决方案3】:

    Segfault(感谢@zneak)意味着以虚拟内存不允许的方式访问内存。在大多数情况下,这是由于试图取消引用 NULL 指针。

    在这种情况下,您反而会遇到缓冲区溢出(这意味着未定义的行为,这意味着它可以很好地在您的计算机上运行并在另一台计算机上崩溃和烧毁)。

    【讨论】:

    • Segfault 意味着以虚拟内存不允许的方式访问内存。它不一定要取消引用 NULL 指针。它可能正在取消引用未映射的地址、写入只读位置或执行不可执行的位置。
    【解决方案4】:

    越过数组的边界在 C 中是未定义的行为。这意味着它是非法的,但是如果/何时发生这种情况,语言不需要做任何特别的事情。

    换句话说,如果你遇到了段错误,那就太棒了!调试起来会更容易。但不幸的是,你不一定会得到一个。在您的情况下,您只是在覆盖相邻的内存。 C 没有关于数组边界的运行时信息,因此无法强制执行。

    在 Linux 系统上,堆栈被分配为一个大的、连续的读写(有时是可执行的)内存块。除非您写入的数据太多以至于超出了堆栈本身的边界,否则您不会遇到分段错误。

    【讨论】:

    • "C 没有关于数组边界的运行时信息,因此无法强制执行它们。"更像是“C 没有指定运行时数组边界”,给定的实现可以强制它们。
    【解决方案5】:

    如果您想检查一些非法内存访问,请使用-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
    

    【讨论】:

      猜你喜欢
      • 2012-10-24
      • 2012-10-02
      • 2019-01-09
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-04-10
      • 2021-07-12
      • 1970-01-01
      相关资源
      最近更新 更多