访问C中的外部分配空间



嗯,我一直认为如果我调用malloc函数,我会分配特定的内存量,但是,我刚刚意识到,如果我写:

int* a = (int*)malloc(sizeof(int) * 2);

我可以为a[4]或任何其他索引分配一个值,我认为在这种情况下,我只能为a[0]a[1]分配。我有什么概念错误?

当您编写a[4]时,它与编写*(a + 4)相同。由于编译器不知道a所指向的地址分配了多少内存,因此它会很乐意让您对内存进行寻址。

然而,位于那里的内存可能是任何东西——它可能是程序使用的另一个变量,堆栈的一部分,或者刚好超出程序的范围。以这种方式访问分配的空间之外可能(往好了说)会产生分段错误,或者(往坏了说)通过覆盖程序的其他部分而引入安全漏洞。

您是正确的,因为您只能安全地分配给a[0]a[1],但C编译器会允许您在该界限之外进行分配(因为它不知道任何不同)。

在您的示例中执行a[4]是不安全的。


此外,最好不要投射malloc的结果-请参阅此答案

在C中,没有办法检查数组是否溢出。您可以继续写入数组之外的内容,直到写入到无效地址或只读页面等。

有一些可用的工具可以让您立即检测,例如当您越过阵列边界时。NAMD就是这样一个工具,它将数组边界之外的直接内存位置设置为只读。

当您访问只读内存时,它会给出SIGSEGV。因此您可以立即检测到数组溢出。

概念错误是相信C会保护你!C相信你知道自己在做什么。您只能真正使用索引0或1,但这不会阻止您使用4(操作系统可能会这样做)。

可以执行a[4]的原因是C不执行任何边界检查。你可以通过数组的边界访问一个单元格,C会这样做

问题是,这是一种非常糟糕的做法,可能是一个安全漏洞。你不应该这样做,因为这可能会导致非常糟糕和不可预见的后果。

未定义的行为就是未定义的。它可能看起来像是在"工作",但事实并非如此。

扩展Keith的答案:您可以覆盖堆上的内存,因为C不进行编译时或运行时绑定检查。a[x]基本上将x * sizeof(x)添加到指针"a"。指针a指向mallocated块的开头。

相关内容

  • 没有找到相关文章

最新更新