【问题标题】:Why can I set a character array larger than I'm reserving with malloc()?为什么我可以设置一个大于我使用 malloc() 保留的字符数组?
【发布时间】:2013-03-12 18:58:48
【问题描述】:

为什么会打印出“test”?:

    char *str;
    str = (char *)malloc(1);
    str[0] = 't';
    str[1] = 'e';
    str[2] = 's';
    str[3] = 't';

我正在尝试动态扩展字符串并尝试了解 malloc/realloc 的工作原理,上述行为让我感到困惑,因为 malloc()/realloc() 建议扩展 char* 。

提前致谢。

【问题讨论】:

  • 因为它是 C 而不是 java... 边界检查允许基于大块进行非常低级别的分页。如果它看起来可以工作,你可能确定你损坏了程序的其他部分,它会在其他地方意外失败...... C 要求程序员注意不要这样做......
  • 在更广泛的问题背景下的次要问题(已经得到回答),但也不要在标准 C 中强制转换 malloc。与 C++ 不同,在 C 中执行此操作被认为是不好的做法,它真正能做的就是隐藏错误(不包括 stdlib.h)并产生代码维护问题,例如:您更改 malloc 调用中使用的变量的类型6 个月后,必须修复石膏。

标签: c string memory dynamic


【解决方案1】:

未定义的行为意味着任何事情都可能发生。包括看起来“工作”,什么都没有,或分段错误。您的示例代码确实很糟糕,但 C 标准不保证它会做任何“有用”的事情,也不保证任何“糟糕”的事情一定会在编译时或运行时发生。

【讨论】:

    【解决方案2】:

    您正在写超出“正式”分配的内存的末尾。大多数内存分配系统都有一个它们在内部使用的最小大小,并且您可能实际上并没有超出 那个 边界,因此您的代码似乎可以正常工作。如果你让字符串足够长,你最终会传递一个对操作系统很重要的边界,你的程序就会崩溃。

    您可以为str 分配一个随机数,然后也将其视为一个指针,并且每隔一段时间它就会真正起作用。但是你不知道你可能在写什么。与您的内存溢出相同。内存分配器可能会将分配压缩得足够紧,以至于您正在覆盖程序中的其他内容。

    您应该始终确保您不会超出任何数组的范围。 永远。缓冲区溢出(和欠载)正是许多黑客利用来侵入系统的原因。确保你不允许它们,并且你已经比那里有相当多的旧代码更好了。

    【讨论】:

      【解决方案3】:

      很明显,这段代码是完全错误的 - 您正在访问超出数组边界的内存。

      它有效,因为:

      • 没有适当的机制来检测每个无效的内存访问。许多这样的尝试会导致分段错误,但并非每次都发生。很多时候,这样的错误代码只是简单地覆盖了一些随机变量等——这就是为什么像这样的调试问题会很快成为一场噩梦的原因之一。我建议你熟悉Valgrind。

      • 在这种特殊情况下,我会说malloc() 将分配的内存块向上舍入到(至少)4 的倍数,因此在这种情况下它可能会按预期工作。但它仍然是一个错误。

      • 你也没有明确地终止字符串,再一次 - 行为真的是随机的,str[4] 可以有任何值,真的。这取决于很多事情——从堆分配器的实现到纯粹的巧合。

      【讨论】:

        猜你喜欢
        • 2011-02-25
        • 2014-08-08
        • 1970-01-01
        • 2021-02-17
        • 2012-09-28
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2014-07-30
        相关资源
        最近更新 更多