如何在VB.Net中定位获取变量的内存地址
VB.Net 提取变量内存地址的实现方法
VB.Net基于CLR运行时,变量内存会受垃圾回收(GC)动态调度影响,不存在永久固定的内存地址,所有获取到的地址仅在特定上下文、不触发GC移动的前提下有效。
核心依赖
实现地址提取需要引入两个系统命名空间:
System.Runtime.InteropServices:提供托管与非托管内存交互的基础操作方法System.Runtime.CompilerServices:提供不安全指针转换、固定内存操作的底层能力
针对示例变量的具体实现
先定义题目给出的基础变量:
' 导入所需命名空间 Imports System.Runtime.InteropServices Imports System.Runtime.CompilerServices Sub ShowVariableMemoryAddress() ' 题目给出的示例变量 Dim x As Integer = 10 Dim y As Integer = 10 Dim s As String = "Test"
值类型变量(x、y)的地址提取
Integer是典型的值类型,默认分配在栈上。要获取原变量的真实栈地址,需要先在项目属性的“生成”页勾选“允许不安全代码”,通过Unsafe.AsPointer直接读取栈上变量的指针:
' 获取x的真实内存地址 Dim addrX As IntPtr = New IntPtr(Unsafe.AsPointer(Of Integer)(x)) Console.WriteLine($"变量x的内存地址: 0x{addrX.ToString("X")}") ' 获取y的真实内存地址 Dim addrY As IntPtr = New IntPtr(Unsafe.AsPointer(Of Integer)(y)) Console.WriteLine($"变量y的内存地址: 0x{addrY.ToString("X")}")
如果不想开启不安全代码权限,可以将值类型复制到临时固定数组中获取等价内存块地址,注意这种方式拿到的是临时复制后的内存地址,不是原栈变量的真实地址。
引用类型变量(字符串s)的地址提取
字符串是引用类型,变量s本身在栈上存储的是指向托管堆对象的引用。要获取堆上对象的地址,必须先通过GCHandle将对象固定,阻止GC在取地址过程中移动对象:
' 固定字符串对象,锁定内存位置 Dim strHandle As GCHandle = GCHandle.Alloc(s, GCHandleType.Pinned) Try Dim addrS As IntPtr = strHandle.AddrOfPinnedObject() Console.WriteLine($"变量s指向的堆内存地址: 0x{addrS.ToString("X")}") Finally ' 操作完成必须释放固定句柄,否则会造成托管内存泄漏 strHandle.Free() End Try End Sub
关键注意事项
- 获取到的所有内存地址都不建议长期持有:未被固定的托管对象随时可能被GC移动,地址失效后继续读写会引发内存访问异常。
- 常量字符串会被CLR做驻留优化,如果两个直接赋值的字符串常量值相同,两个变量会指向同一个堆内存地址。
- 固定句柄不要跨线程持有,跨场景使用需要补充对应的同步逻辑。
内容的提问来源于stack exchange,提问作者Sougata
相关产品推荐
相关产品推荐

