一个数组在内存中是如何存储的?

7

为了更深入地了解内存如何被分配和存储,我编写了一个应用程序,它可以扫描内存地址空间,查找一个值,并写出一个新的值。

我开发了一个示例应用程序,最终目标是能够以编程方式定位我的数组,并用一个新的数字序列覆盖它。在这种情况下,我创建了一个包含5个元素的单一维度数组,例如:

int[] array = new int[] {8,7,6,5,4};

我运行了我的应用程序,并搜索了上面的五个数字序列。我正在寻找任何在4和8之间的值,总共有5个连续数字。不幸的是,我的数组中的顺序数字匹配了数百个结果,因为数字4到8没有特定的顺序,它们恰好相邻,存在于许多情况下的内存中。
有没有办法区分内存中的一组数字表示一个数组,而不仅仅是相邻的整数?是否有任何方法知道如果我找到某个值,其后的匹配值是数组的值?
我会假设当我声明int []array时,它指向了我的数组的第一个地址,这将提供一些关于数组中存在的元数据,例如:
0x123456789 meta-data, 5 - 32 bit integers 
0x123456789 + 32 "8"
0x123456789 + 64 "7"
0x123456789 + 96 "6"
0x123456789 + 128 "5"
0x123456789 + 160 "4"
我离谱了吗?

什么?int[] array = new array {8,7,6,5,4}; - user541686
5个回答

8

调试 + Windows + 内存 + 内存 1,将地址字段设置为 "array"。当您将视图切换为“4字节整数”时,您会看到这个:

0x018416BC  6feb2c84 00000005 00000008 00000007 00000006 00000005 00000004

第一个地址是垃圾回收堆中对象的地址,再加上对象头部分在负偏移量(syncblk index)处的地址。这个值是无法猜测的,因为垃圾回收会将其移动。第二个十六进制数字是数组类型的“类型句柄”(也称为方法表指针)。这个值也是无法猜测的,因为类型句柄是由CLR按需创建的。第三个数字是数组长度,其余数字是数组元素的值。
在没有调试器的情况下,可靠地在运行时找到这个数组的可能性非常低。因此尝试这样做并没有太多意义。

如果第三组数字表示数组的长度,并且在它之后的数字匹配了已知数字和长度的目标范围,我可以看到这种方法非常接近。例如,如果我要搜索000000FF,知道我有一个长度为255的数组,然后测试接下来的255个数字是否在我知道的数组范围内,比如0-5,那么在代码中找到完全相同的组合的可能性似乎很小。然而,匹配它的机会会随着我声明的数组越小而变得更小。 - George Johnston
好的,地址是4的倍数。模糊性是问题所在,你没有任何东西可以选择“正确”的那个。而且有多达20亿字节要搜索。VirtualQuery可以缩小范围,只考虑读写页面。 - Hans Passant
我根据您提到的第三个数字集和我定义的其他一些抽象搜索规则修改了我的应用程序,以便快速而彻底地枚举进程地址空间。在瞬间找到了我的数组,而且只有我的数组。非常感谢! - George Johnston

0

不要这样做。数组存储在堆上,可能会因为垃圾回收而被重新定位。如果您需要确保内存不会移动,您必须使用fixed,但只能非常小心地使用。

如果您需要高性能的数组,请使用stackalloc并使用您的代码方案。


我这里除了想知道上面的示例在声明时会如何存储之外,没有别的目的。数组在垃圾回收期间发生什么是我所问的范围之外的。只是为了学习而已。 :) - George Johnston

0

我不确定,但这篇文章似乎表明您可以获得指向数组的指针,通过它您可以确定实际地址。


0

虽然我看到你正在使用C#和.NET,但你的问题大部分都是关于内存的一般性问题。请记住,在最一般的意义上,所有的内存都只是位,无论这个内存是包含数组、字符串还是代码。

有了这个想法,除非你能找到当前平台分配不同数据类型的方式的明显迹象,否则包含数组、字符串或代码的内存之间没有区别。

此外,我不会做出任何关于数组是否“指向”数组中的第一个项的假设。也许其他人可以具体解决这个问题,但我会假设涉及某种头文件。


同意。我已经移除了C#标签。 - George Johnston
在这种情况下,我会说你问题的答案是否定的。 - Jonathan Wood

-1

内存并不总是连续存储的。如果您可以确保它是连续的,那么您所要求的是可以实现的。


4
数组在虚拟内存中是连续存储的。连续的虚拟内存并不意味着连续的物理内存,但如果这个“扫描应用程序”正在使用物理地址,我会非常惊讶。只有在使用硬件DMA引擎扫描内存时才需要担心这些详细信息。 - Ben Voigt

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接