我对C编程比较陌生,很难理解整个内存分配问题。
让我们说,我做:
int *n = malloc(sizeof(char));
// (assuming malloc doesn't return NULL of course)
提供了一个指向int的指针,但是我没有为int分配足够的内存。为什么它能起作用呢?我甚至可以显式地将它强制转换为int,这不会影响到gcc。我知道C编译器是非常简约的,但即使我给*n赋值,它也不适合字符,比如:
*n = 300;
…然后打印出来:
printf("%d", *n);
…它工作得很好,虽然现在我最希望出现一些错误,如分割错误。
我的意思是,sizeof(char)在我的机器上是1 sizeof(int)是4。因此,3个字节被写入内存中没有正确分配的某个位置。
仅仅因为它没有离开堆栈就可以工作吗?
谁能告诉我一个地方,我可能会找到有关这些东西的启示?
提供了一个指向int的指针,但是我没有为int分配足够的内存。为什么它能起作用呢?
malloc的返回值是void*
,语言允许将其隐式转换为任何指针类型,在本例中是int*
。编译器通常不包含检查传递给malloc
的内容是否满足特定大小要求的行为,在现实世界的代码中,这可能非常困难(当编译时不知道的非常量大小传递给malloc时)。正如你所说,C编译器通常是相当简单的。有一些"静态分析"工具可以通过分析代码来找出bug,但这是与编译器完全不同的一类工具。
…它的工作非常好,虽然现在在最新的我期望一些错误,如分割错误。我的意思是,sizeof(char)在我的机器上是1 sizeof(int)是4。因此,3个字节被写入内存中没有正确分配的某个位置。
写超出已分配内存的界限是所谓的"未定义行为"。这意味着当这种情况发生时,兼容的编译器可以做任何它想做的事情。有时它会崩溃,有时它会重写程序中的其他变量,有时什么也不会发生,有时似乎没有发生,您的程序将在以后的日期崩溃。
在这个特殊的情况下,发生的事情是,大多数malloc
的实现分配至少16字节(或多或少,如8或32),即使您要求更少。因此,当您覆盖单个分配的字节时,您将写入没有用于任何用途的"额外"内存。强烈建议不建议您在任何实际程序中依赖该行为。
仅仅因为它没有离开堆栈就可以工作吗?
堆栈与这种特殊情况无关。
谁能告诉我一个地方,我可能会找到有关这些东西的启示?
任何一本好的C书都会有这类信息,看看这里:权威C书指南和列表
通常32位机器会在32位边界上分配新的内存-这使得内存访问更快。
所以它已经分配了一个字节,但接下来的3个字节是未使用的
不要依赖这个!