【问题标题】:C malloc function sizeC malloc 函数大小
【发布时间】:2016-05-07 04:49:37
【问题描述】:

所以我有一个小问题需要回答:

如果函数是,c+9指向内存中的哪个段:

void f() 
 { 
  int *c=(int*)malloc(10); 
 }

我想我知道 malloc 是如何工作的,并且我查看了其他问题,所以这应该分配 10 个字节的内存并返回第一个字节的地址,再加上它将它转换为 int。

所以因为sizeof(int)是4个字节,所以我认为9个整数不会有足够的空间,c+9会指向分配内存范围之外的一些内存,它会返回错误,但是不,程序运行得很好,好像分配了10*sizeof(int)。那么我在哪里做错了?

【问题讨论】:

  • c + 9&c[9] 相同,但假设c 实际上是指向至少10 个元素的数组的指针。您的代码中不是这种情况。
  • 我知道,但是这里的代码在我使用时可以正常工作,我不是在制作程序,这是一个问题。例如,当我制作程序时,我使用 malloc( 10 * sizeof (int) )。但这是一个测试我对 C 工作原理的了解的问题。
  • 当您使用超出范围的内存时,您有未定义的行为。在大多数情况下,您不会收到任何编译时错误。它也不必抛出异常。此外,如果您不需要,编译器可能会优化内存访问。

标签: c memory-management casting malloc sizeof


【解决方案1】:

您的错误是认为它可以正常工作

是的,它可能会运行,是的,它可能没有段错误,但是不,它不正确。

所以因为sizeof(int)是4个字节,我以为不会有足够的空间容纳9个整数,而c+9会指向一些超出分配内存范围的内存

这是正确的

它会返回一个错误

但不幸的是,这并非在所有情况下都是正确的。操作系统只能提供整页空间,这意味着您只能获得 4096 字节(一页)的倍数的空间。这意味着,即使 malloc(在用户空间中实现)为您提供 10 个字节,您的程序将至少有 4096 个字节来自操作系统。 但是:malloc最终会从你获得的这一页中为你提供更多未分配的空间,然后它可能会引入一个错误。

TLDR:这是 UB,即使它看起来有效,但永远不要这样做。

【讨论】:

    【解决方案2】:

    您错误地假设未定义的行为意味着肯定会发生“坏”的事情。在您的情况下访问 c[9] 是未定义的行为,因为您没有 malloced 足够的内存 - 这是您不应该做的事情。

    未定义行为意味着标准允许任何行为。对于这个特定的错误,您经常会遇到非本地化的错误行为,访问c[9] 显然可以正常工作,并且在您执行此操作时不会发生奇怪的事情,但随后在不相关的代码段中访问不相关的数据段会导致错误。通常这些错误也会破坏内存分配系统使用的数据,这可能会使mallocfree 行为不端。

    【讨论】:

      【解决方案3】:

      如果您在分配的内存范围之外进行操作,C 程序将不会返回错误。结果未定义,它可能会挂起或(显然)工作正常。但这并不好。

      【讨论】:

      • 所以我可以访问其他一些程序的内存并可能导致它崩溃?
      • 是的。或者可能 malloc 分配了 16 个字节而不是 10 个。但你不知道。
      • @Nebeski 不,由于虚拟内存管理,这在现代操作系统中是不可能的。
      • 谁说过现代操作系统?您甚至可以在没有操作系统的系统中使用 C。
      • 如果您的程序直接作为 内核 运行,或者没有其他程序崩溃。
      【解决方案4】:

      你是对的,malloc 给你 10 个字符(通常是 8 位字节)。为ints 分配一个不是int 大小倍数的区域本身就是可疑的......但不是非法的。结果地址被解释为指向int(通常为32 位)的指针,并且您要求地址9 int 超出分配区域的开头。这本身很好,但试图访问它是未定义的行为:任何事情都可能发生,包括你天真地期望的任何事情,什么都没有,崩溃或终结宇宙。 通常会发生的是,您从包含其他对象和可用空间的更大区域获得分配的内存(以及malloc 用于跟踪整个混乱的额外数据)。 读取不会造成伤害,写入可能会损坏其他数据或弄乱malloc 的数据结构,从而导致稍后出现神秘行为/崩溃。如果幸运的话,新空间是在边界分配的,超出限制的访问会导致分段错误,指向罪魁祸首。

      【讨论】:

        猜你喜欢
        • 2014-09-14
        • 2016-06-23
        • 1970-01-01
        • 1970-01-01
        • 2021-07-09
        • 1970-01-01
        • 1970-01-01
        • 2013-02-04
        • 2021-02-20
        相关资源
        最近更新 更多