我知道 int 变量(值类型)是否直接在类中声明(引用类型 >),在堆上分配的变量的内存。
但是如果类中有方法并且变量是在方法内声明的,或者是参数,则在堆栈上分配内存。
public class A
{
int x; // heap
public void Func(int y) // stack
{
int z; // stack
}
}
我怎样才能看到内存的分配位置?
答案 0 :(得分:4)
当你说'内存位于'时, 我假设你的意思是赋予变量的实际虚拟地址, 也许是它驻留在私有字节中的已提交块或区域。 虽然这种琐碎充满活力,但它可能会被移动 (这就是为什么本地互操作开发人员必须在使用前固定内存), 您可以搜索类似于以下内容的变量位置:
给定源(和断点):
允许反汇编(选项 - >调试 - >常规 - >显示反汇编......) 右键单击(上下文菜单):选择'转到反汇编'
注意z的分配:
mov dword ptr [ebp-44h],eax
打开寄存器窗口(Debug - > Windows - > Registers)。 注意EBP(基指针)的值== 0x05C0EF18。
使用calc(程序员模式)从上面确定[ebp-44h]。 0x05C0EF18 - 0x44 == 0x05C0EED4
查看该内存位置(Debug - > Windows - > Memory - > Memory 1) 粘贴结果值(此实例为0x05C0EED4)。
注意值
87 d6 12 00 // <-- Little Endian (00 12 d6 87 <-- Big Endian)
// 0x0012D687 (hex) == 1234567 (decimal)
我们可以确定(现在)z位于0x05C0EED4 并且有1234567(十进制)存储在它的位置。
然而,x有点复杂。 x位于EAX + 4。
// Similar exercise as above...
// values get moved into registers, then the assignment...
mov eax,dword ptr [ebp-3Ch] // [ebp-3Ch] == 0x05C0EF18 - 0x3C == 0x05C0EEDC
// Move the value at 0x05C0EEDC (7c d4 40 02) to EAX
// [7c d4 40 02] (Big Endian) --> [02 40 d4 7c] (Little Endian)
// [02 40 d4 7c] (Little Endian) == 0x0240d47c or 37803132 (decimal)
mov edx,dword ptr [ebp-40h] // [ebp-40h] == 0x05C0EF18 - 0x40 == 0x05C0EED8
// Move the value at 0x05C0EED8 (87 d6 12 00) to EDX
// [87 d6 12 00] (Big Endian) --> [00 12 d6 87] (Little Endian)
// [00 12 d6 87] (Little Endian) == 0x0012d687 or 1234567 (decimal)
mov dword ptr [eax+4],edx // [EAX == 0x0240d47c] + 4 = 0x240D480
// Move the value at EDX (0x0012d687 or 1234567 (decimal)) to
// EAX+4 (x variable located at 0x240D480)
// (currently holds [b1 cb 74 00] (Big Endian)
// which is equal to 7654321 (decimal)
然而,虚拟内存映射也很有趣。使用sysinternals中的vmmmap.exe可以更好地了解保留页面和已提交页面。然后,您可以在GC等不同代中找到它们。
希望这有帮助!