【问题标题】:Allocating less space then necessary for a certain type?为某种类型分配更少的空间?
【发布时间】:2011-12-13 16:23:57
【问题描述】:

我对 C 编程比较陌生,很难理解整个内存分配问题。

假设,我愿意:

int *n = malloc(sizeof(char));
// (assuming malloc doesn't return NULL of course)

这提供了一个指向 int 的指针,但我没有为 int 分配足够的内存。为什么它会起作用?我什至可以将它显式地转换为 int 并且它不会打扰 gcc。我知道 C 编译器非常简约,但即使我为 *n 分配了一个值,它也不适合 char,例如:

*n = 300;

...然后打印出来:

printf("%d", *n);

...它工作得非常好,尽管最迟我预计会出现一些错误,例如分段错误。

我的意思是,sizeof(char) 在我的机器上是 1,而 sizeof(int) 是 4。因此 3 个字节被写入内存中的某个未正确分配的位置。

它只是因为它不离开堆栈而起作用吗?

有人能指点我一个地方,我可能会发现关于这些东西的启示吗?

【问题讨论】:

  • 如果您遇到了段错误,请认为自己很幸运。没有段错误并不意味着你的代码很好,它只是意味着你被搞砸了,因为你没有得到任何迹象表明它是错误的......直到你切换编译器,编译器版本,架构等并且东西爆炸或给出错误的结果.可悲的是,很容易得到那种。
  • 请注意,sizeof (char) 根据定义为 1(尽管这与您的问题并不特别相关)。 sizeof 产生的结果是多个字节,但一个字节被定义为 char 的大小(通常是 8 位,但可以更多)。

标签: c memory memory-management malloc


【解决方案1】:

这提供了一个指向 int 的指针,但我没有为 int 分配足够的内存。那为什么会起作用呢?

malloc 的返回值为void*,该语言允许将其隐式转换为任何指针类型,在本例中为int*。编译器通常不包含检查您传递给malloc 的内容是否满足特定大小要求的行为,这在实际代码中可能非常困难(当编译时未知的非常量大小传递给malloc 时)。正如您所说,C 编译器通常相当简约。有诸如“静态分析”工具之类的东西可以分析代码以试图找到这些错误,但这是与编译器完全不同的一类工具。

...它工作得非常好,尽管现在最迟我预计会出现一些错误,比如分段错误。我的意思是,在我的机器上 sizeof(char) 是 1 而 sizeof(int) 是 4。因此 3 个字节被写入内存中的某个未正确分配的位置。

超出分配内存的范围写入是所谓的“未定义行为”。这意味着兼容的编译器可以在发生这种情况时为所欲为。有时它会崩溃,有时它会覆盖您程序中的其他变量,有时什么都不会发生,有时什么都不会发生似乎,您的程序会在以后崩溃。

在这种特殊情况下,即使您要求更少,malloc 的大多数实现也会分配至少 16 个字节(或更多或更少,例如 8 或 32)。因此,当您覆盖单个分配的字节时,您正在写入未用于任何内容的“额外”内存。 强烈不建议您在任何实际程序中依赖这种行为。

它只是因为它不离开堆栈而起作用吗?

堆栈与这种特殊情况无关。

有人能指点我一个地方,我可能会发现关于这些东西的启示吗?

任何好的C书都会有这种类型的信息,看这里:The Definitive C Book Guide and List

【讨论】:

    【解决方案2】:

    通常 32 位机器会在 32 位边界上分配新内存 - 它使内存访问速度更快。
    所以它已经分配了一个字节,但是接下来的 3 个字节是未使用的

    不要依赖这个!

    【讨论】:

    • 实际上,它很可能已经分配了 8 个可用字节(足够包含两个指针来将内存块在被释放时链接到一个链表中,分配器并不关心那些不是释放)。
    猜你喜欢
    • 2021-12-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-05-14
    • 2022-01-02
    • 1970-01-01
    相关资源
    最近更新 更多