我对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个字节被写入存储器中尚未正确分配的某个位置 .
它只是因为它没有离开堆栈吗?
有人可以指点我到一个可以找到有关那些东西的启示的地方吗?
2 回答
malloc的返回值是
void*
,该语言允许将其隐式转换为任何指针类型,在本例中为int*
. 编译器通常不包括检查传递给malloc
的内容是否满足特定大小要求的行为,在实际代码中可能非常困难(当编译时未知的非常量大小传递给malloc时) . 正如你所说,C编译器通常是极简主义的 . 有一些"static analysis"工具可以分析代码以试图找到这些错误,但这是一个完全不同的工具类而不是编译器 .写入超出已分配内存的范围就是所谓的"undefined behavior" . 这意味着兼容的编译器可以在发生这种情况时执行任何操作 . 有时它会崩溃,有时它可以写入程序中的其他变量,有时什么都不会发生,有时似乎什么都不会发生,你的程序将在以后崩溃 .
在这种特殊情况下,正在发生的事情是
malloc
的大多数实现分配最少16个字节(或更多或更少,如8或32),即使您要求更少 . 因此,当您覆盖单个分配的字节时,您正在写入"extra"内存,而该内存并未用于任何内容 . 强烈建议您不要在任何实际程序中依赖该行为 .堆栈与此特定情况无关 .
任何好的C书都会有这种类型的信息,请看这里:The Definitive C Book Guide and List
通常,32位机器将在32位边界上分配新内存 - 它使内存访问更快 .
所以它已经分配了一个字节,但是接下来的3字节是未使用的
不要依赖于此!