显示静态和动态分配之间差异的C代码

时间:2015-08-21 05:49:11

标签: c arrays memory memory-management

我想编写一个C代码来查看静态和动态分配之间的区别。

这是我的想法,但它没有用。

它只是初始化一个大小为10的数组,但是分配100个元素而不是10.然后我会初始化另一个足够大的数组,希望能够替换90个元素。不属于array1[10],我打印出100的{​​{1}}元素。

array1

我希望得到的是使用静态分配时的前10个元素以外的垃圾,之后,我将使用malloc和realloc来确保100个元素正确存在。但不幸的是,似乎内存足够大,以至于100个元素的其余部分都不会被替换!

我尝试在linux上运行代码并使用" ulimit"限制内存大小,但它也没有。

有什么想法吗?

5 个答案:

答案 0 :(得分:4)

C实际上没有对数组进行任何边界检查。这取决于操作系统,以确保您访问有效的内存。

从数组边界外部访问是未定义的行为,来自c99 draft standard部分附件J.2 J.2未定义的行为包括以下几点:

  

数组下标超出范围,即使某个对象显然可以使用   给定下标(如左边的表达式a [1] [7]给出声明int   a [4] [5])(6.5.6)。

在此示例中,您将声明基于堆栈的数组。访问越界将从已分配的堆栈空间获取内存。目前未定义的行为不利于您,因为没有Seg故障。它的程序员负责在用C / C ++编写代码时处理边界条件。

答案 1 :(得分:1)

当您访问array1[10]及更高的索引值时,程序将继续写入相邻的内存位置,即使它们不属于您的阵列。在某些时候,您可能会尝试访问被禁止的内存位置,但只要您查看操作系统为您的程序提供的内存,就会运行。但结果将无法预测。例如,可能会损坏属于程序中另一个变量的数据。如果没有其他变量“已正确分配”该内存位置,那么当您返回读取它时,您所写的值仍然会存在。 (这似乎是您发布的特定案例中发生的情况。)

所有这一切,我都不清楚这与静态和动态内存分配之间的潜在差异有什么关系,因为你只是在程序中进行了静态分配而且你故意引入了一个bug。

答案 2 :(得分:1)

array1的前10个元素后获取垃圾。元素9之后的所有数据不应被视为由堆栈分配,并且可以随时写入。当程序打印出array1的100个元素时,您可能会看到for循环的残余,因为这两个数组是彼此相邻分配的,通​​常都没有被写过。如果这是在一个更大的程序中实现的,那么其他数组可能占用这两个示例数组之后的空间。

答案 3 :(得分:0)

更改内存大小无法解决您的问题,因为当您创建两个阵列时,第二个阵列应该内存后第一个阵列。

您的代码应该按照您的想法执行,并且在我的计算机上执行。 这是我的输出: 0 1 2 3 4 5 6 7 8 9 10 11 1 2 3 4 5 ...

您运行代码的操作系统是什么? (我在linux 64bit上)。

无论如何,正如每个人都告诉你的那样,不要在真正的程序中执行此操作。在数组外部编写是一种未定义的行为,可能导致程序崩溃。

答案 4 :(得分:0)

写出超出数组的范围将证明什么都没有,并且没有明确定义。通常,调用未定义的行为没有任何巧妙或有趣的内容。你唯一能做到的就是随机崩溃。

如果您想知道变量的分配位置,您必须查看地址。这是一个例子:

#include <stdio.h>
#include <stdlib.h>

int main (void)
{
  int stack;
  static int data = 1;
  static int bss  = 0;
  int* heap = malloc(sizeof(*heap));

  printf("stack: %p\n", (void*)&stack);
  printf(".data: %p\n", (void*)&data);
  printf(".bss:  %p\n", (void*)&bss);
  printf(".heap: %p\n", (void*)heap);
}

这应该打印4个截然不同的地址(.data和.bss可能彼此相近)。要确切知道某个内存区域的起始位置,您需要检查一些链接描述文件或使用特定于系统的API。一旦知道了存储区的偏移量和大小,就可以确定变量是否存储在其中一个不同的内存段中。