【问题标题】:Array, allocation, perplexion数组,分配,困惑
【发布时间】:2010-10-29 13:44:31
【问题描述】:
#include <stdio.h>
#include <stdlib.h>

int main()
{
    int *numeros = malloc(sizeof(int) * 3 * 3);
    numeros[900] = 10;
    printf("%d", numeros[900]);
    free(numeros);
    return 0;
}

当我没有分配足够的内存时,为什么会打印出 10? 我很确定我在指针/等方面遗漏了一些重要的东西。

感谢您的帮助

【问题讨论】:

    标签: c arrays


    【解决方案1】:

    您观察到的是未定义的行为 - 您在分配的缓冲区之外写入,并且可能会覆盖一些恰好映射到进程中的内存。

    根据各种因素,这可能会使您的程序崩溃,或者什么都不做或损坏程序中的数据。不要这样做,只访问您合法分配的内存。

    另见this related question

    【讨论】:

    • 半开玩笑它也可能在操作系统的某些部分写10,因此,格式化你的硬盘:-)
    • @pmg: 是的,或者通过网络发送你所有的密码——类似于这个 UB 实例stackoverflow.com/questions/908872/…
    【解决方案2】:

    您的数组大小为 9。因此,当您尝试访问超出范围的内存位置 900 时。

    你的行为是undefined。意思是,有时它可能会打印垃圾值,有时它可能会崩溃。因此,请务必在使用前初始化您的 var。

    【讨论】:

      【解决方案3】:

      您缺少的是编译器不需要捕捉这种情况,而且通常不会。这是未定义的行为,这意味着对于实现的功能没有任何要求,避免它是您的工作。通常,编译器只会编译它看到的任何未定义行为,有时出现的合理行为可能会令人困惑。

      在这种情况下,您在numeros 中存储了一个内存地址,并且在下一个引用*(numeros + 900) 的语句中,给定通常的int 大小将是内存地址之后的3600 个字节。编译器生成代码供参考。考虑到这是未定义的行为,编译器这样做是完全正确的,或者就此向您或您的母亲写一封侮辱性的电子邮件;该标准没有规定任何内容。当然,它可以检测到这一点并给你一个运行时错误,说“第 7 行的地址超出范围”,但不幸的是,我使用的编译器都没有给你这个选项。

      这是 C 编程中比较棘手的部分之一:确保您的程序定义明确。

      【讨论】:

      • +1:你的帖子让我想起了我在某处读到的一句话:C 编译器信任程序员。对编译器撒谎,它会报仇的
      【解决方案4】:

      您使用 malloc 为 9 个元素分配了内存:

       int *numeros = malloc(sizeof(int) * 3 * 3); 
              // allocates memory of (4) *(9) bytes==36 bytes
      

      现在您的数组边界应该在您为其分配内存的 int 的限制内,这是您乘以 sizeof(int) 的数字。它为尽可能多的 int 分配内存。

      【讨论】:

        【解决方案5】:

        您能够这样做是因为您从堆中分配了您的数组,这可能至少有 32K。所以你正在做的是写入堆中的其他位置,这是“合法的”。如果您将数组索引提高到 128000 左右,您可能会遇到访问冲突。实际上,您(可能)正在覆盖您分配的其他一些数据,或者可能是实际的堆管理元数据(块头)。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2021-11-16
          相关资源
          最近更新 更多