我对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个字节被写入内存中尚未正确分配的某个位置。
它只是因为没有离开堆栈吗?
有人可以请我指一个我可能会找到有关那些东西的启示的地方吗?
答案 0 :(得分:7)
它提供了指向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
答案 1 :(得分:2)
通常,32位机器将在32位边界上分配新内存 - 它可以更快地访问内存 所以它已经分配了一个字节,但接下来的3字节是未使用的
不要依赖于此!