#include <stdio.h>
#include <stdlib.h>
int main()
{
int *numeros = malloc(sizeof(int) * 3 * 3);
numeros[900] = 10;
printf("%d", numeros[900]);
free(numeros);
return 0;
}
为什么当我没有分配足够的内存时,这打印出10? 我很确定我在指针等方面缺少一些重要的东西。
感谢您提供帮助
答案 0 :(得分:14)
您观察到的是未定义的行为 - 您在分配的缓冲区之外写入并可能覆盖恰好映射到流程中的某些内存。
根据各种因素,这可能会导致您的程序崩溃,或者只是不执行任何操作或损坏程序中的数据。不要这样做,只访问你合法分配的内存。
答案 1 :(得分:1)
您的数组大小为9.因此,当您尝试访问超出范围的内存位置900时。
您的行为是undefined
。意思是,有时它可能会打印垃圾值,有时它可能会崩溃。因此,请在使用前始终初始化您的变量。
答案 2 :(得分:1)
您缺少的是编译器不需要捕获这种情况,通常也不会。这是未定义的行为,这意味着没有关于实现的要求,并且您的工作就是避免它。通常情况下,编译器只会编译在未定义行为的情况下看到的任何内容,并且出现的有时合理的行为可能会令人困惑。
在这种情况下,您将存储器地址存储在numeros
中,并在下一个引用*(numeros + 900)
的语句中存储,其中通常的int
大小将在存储器地址之后为3600字节。编译器生成了引用的代码。考虑到这是未定义的行为,编译器完全正确,或者就此而言,向您或您的母亲写一封侮辱性的电子邮件;标准没有任何规定。当然,它可以检测到这一点并给你一个运行时错误,说“在第7行超出界限”,但不幸的是,我用过的编译器都没有给你这个选项。
这是C编程中比较棘手的部分之一:确保您的程序定义明确。
答案 3 :(得分:0)
您使用malloc分配了9个元素的内存:
int *numeros = malloc(sizeof(int) * 3 * 3);
// allocates memory of (4) *(9) bytes==36 bytes
现在你的数组边界应该在你为你分配内存的int的限制范围内,这是你用你的sizeof(int)乘以的数字。它为int分配了内存。
答案 4 :(得分:0)
你能够这样做是因为你已经从堆中分配了你的数组,这可能至少是32K。所以你要做的就是写入堆中的其他位置,这是“合法的”。如果您将阵列索引提升到128000左右,则可能会出现访问冲突。实际上,您(可能)会覆盖您已分配的其他一些数据,或者可能覆盖实际的堆管理元数据(块头)。