繁体   English   中英

Windows中分配的内存的内容

[英]Contents of allocated memory in Windows

我玩过C语言和其他排序算法。 我没有生成随机数组进行排序,而是决定尝试声明某种大小(例如100)的自动数组,而不进行初始化。 我期望操作系统(我在Windows XP上)将零放在其中,否则可能是其他进程留下的一些数据。 但是事实证明,在这种未初始化的数组中没有零。 因此,第一个问题是:它可能是什么数据,为什么操作系统不清除它? 难道我正在运行编译器和程序的“ cmd” shell的垃圾?

接下来,由于我尝试的排序算法不再分配更多的内存,而是将所有内存都放在适当的位置,所以我认为有两种可能性:(a)为数组分配的内存区域将被排序并保持不变下次运行时,或(b)下次运行时,操作系统将为程序提供另一部分内存,并因此为您提供另一种垃圾。 但事实证明,事实并非如此。 无论我对内存进行多少次排序,内存都保持不变。 因此,第二个问题是:我怎么可能得到一个随机的虚拟内存区域,对其进行排序,而在下一次运行时,我会得到其原始形式的相同区域?

下面是代码和我的步骤。

#include <stdio.h>
#define SIZE 100

void quick_sort( int *a, size_t size )
{
     /* No comments here, everybody knows quicksort
     and anyone will write it better! :) */

     if( size <= 1 ) return;

     int tmp, pivot;
     int small_length, pivot_pos;

     pivot_pos = size / 2;
     pivot = a[pivot_pos];
     tmp = a[0];
     a[0] = pivot;
     a[pivot_pos] = tmp;

     small_length = 0;

     for( int i = 1; i < size; i++ )
     {
      if( a[i] < pivot ){
           small_length++;
           tmp = a[small_length];
           a[small_length] = a[i];
           a[i] = tmp;
      }
     }

     a[0] = a[small_length];
     a[small_length] = pivot;

     quick_sort( a, small_length );
     quick_sort( a + small_length + 1, size - small_length - 1 );
}

int main( int argc, char *argv[] )
{
     int a[SIZE];
     int i;

     quick_sort( a, SIZE );
     for( i = 0; i < SIZE; i++ ) {
        printf( "%d\n", a[i] );
     }
     return 0;
}

我使用的步骤:

  1. 使用带有注释的quick_sort调用进行编译,以查看未排序的统一数组: cc sort.c -Wall -std=c99 && a > unsorted1 (已编译的可执行文件为a.exe )。
  2. 取消对quick_sort调用的注释,并查看排序结果: cc ... > sorted
  3. 再次注释该调用以再次查看未排序的数组: cc ... > unsorted2
  4. 比较文件unsorted1unsorted2它们相同,所有100行。

我也尝试启动“ cmd”的另一个实例,并且数据是相同的。

更新

I.未分类数据的十六进制转储:

0000000 0000 0000 fd7c 0022 fd74 0022 fdd8 0022
0000020 0170 0000 1448 7c91 ffff ffff 1440 7c91
0000040 0000 0024 13d2 7c91 301c 0024 3008 0024
0000060 0010 0000 b988 7c97 0000 003e 0007 0000
0000100 fd24 0022 0000 0000 fe24 0022 e900 7c90
0000120 0040 0001 002e 0000 0000 003e eeeb 7c80
0000140 fe30 0022 e900 7c90 0040 7c91 ffff ffff
0000160 003d 0001 0002 0000 fd5c 0022 0000 0000
0000200 fe50 0022 0002 0000 0002 0000 ffff ffff
0000220 003d 7c91 c2de 77c1 0000 003e 0000 0000
0000240 c2e3 77c1 a122 0040 0000 0000 2bc4 003e
0000260 2070 77c0 ffff ffff 0000 003e 2bc0 003e
0000300 0004 0000 2373 0024 1660 0040 fea0 0022
0000320 c024 77c1 0000 003e 0000 0000 c02d 77c1
0000340 1660 0040 2373 0024 1dc0 0040 fec0 0022
0000360 c024 77c1 0000 003e 0000 0000 c02d 77c1
0000400 1dc0 0040 2373 0024 0000 0000 5c94 77c2
0000420 a52e 77c2 1ae8 77c5 fedc 0022 9d60 77c2
0000440 fe88 0022 4e2f 77c2 feec 0022 5c94 77c2
0000460 a52e 77c2 1ae8 77c5 fefc 0022 9d60 77c2
0000500 0008 0000 4e2f 77c2 4e29 77c2 ff3c 0022
0000520 2373 0024 0000 0000 1dc0 0040 fed4 0022
0000540 ff08 0022 ffe0 0022 5c94 77c2 2850 77c0
0000560 ffff ffff 4e29 77c2 4e42 77c2 1dc0 0040
0000600 ffa0 0022 1e1e 0040 1dc0 0040 0020 0000

要生成转储,我必须在代码中添加一个FILE,fopen(...),fclose(...),然后更改了输出。 但是这些调用是在数组声明之后进行的,因此仍然不确定如何影响数组的内容。

II。 尝试将SIZE增加到10000,最后看到零。 输出是许多零,最后是那个熟悉的垃圾。 我不确定内存的增长方向,我希望数据保留在数组的开头...

现代的多用户/多进程操作系统始终将干净的内存页面移交给请求内存的进程(这样敏感数据就不会从一个进程泄漏到另一个进程)。 请注意,仅当操作系统最初将内存移交给进程时,此“干净”协定才适用。 如果该过程最初将内存用于一件事情,然后再用于其他事情,则不会自动重新清理内存。 这就是这里发生的事情-您的未初始化变量在堆栈上,并且在main运行之前C运行时启动代码已使用该堆栈。 您会看到堆栈上残留了很多启动代码。 如果您确切地想知道它是什么,可以阅读Microsoft Visual C运行时库源代码(Visual Studio附带),或在反汇编器中查看程序入口点的反汇编。

堆也是如此。 mallocVirtualAlloc等首先从操作系统获取页面时,它们将是干净的。 但是,当您调用freeVirtualFree等时,运行时库没有义务将页面返回给操作系统并重新请求它们。 它可以只握住它们(不清洗它们)并使用它们来满足以后的要求。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM