为了账号安全,请及时绑定邮箱和手机立即绑定

最简单的VB指针

标签:
资讯

      用过VB写过点程序的朋友都知道,涉及到内存地址访问的时候,CopyMemory这个API是少他不了的。的确用了这个API给死板的VB带来了不少的灵活性,然而仅仅作为一个内存读写的指令,却要要用API函数来实现,其中的开销自然不言而喻。难道不用API,VB就没有别的办法访问内存了吗?当然不是!

      在C里面,与指针这个东西最相似的当然就是数组,当你把数组的索引超过了其自身的长度,将会访问到数组以外的数据,甚至发生崩溃。但在VB里这种现象却不会发生——当你超越了数组的界限时,将会产生一个运行时错误以阻止这个操作的运行。这时因为VB为你程序的安全性考虑,以不至于产生一些安全性的问题,当然,这是以牺牲运行效率换来的。可见,正是这个多余的安全检查,阻碍了变量灵活访问的权限。事实上,数组的界限检验是可以关闭的!那么,当数组的索引超过了其界限,访问到的自然就是内存数据了。

新建一个只有模块的工程,在菜单工程->属性->编译->高级优化里,选上“取消数据绑定检查”,然后:

Option Explicit
 
Dim MEM(0) As Byte
Dim BASE As Long
 
Sub Main()
    Dim src As Byte
    Dim pValue As Long
 
    BASE = -VarPtr(MEM(0))
 
    src = 123
    pValue = VarPtr(src)
 
    MsgBox MEM(BASE + pValue)
End Sub

 

      首先声明一个MEM的字节型数组,当作是内存,BASE变量保存MEM数组的地址,当作是一个基地址。因为变量顺序问题,这里把它取负。当知道某个变量的地址,比如pValue时,直接MEM(BASE + pValue)便可访问那个指针所指向的内存了。

      编译EXE后运行,果然可以!不过按下F5调试,出错了?是的,VB那所谓的取消数组绑定只在编译以后才能起作用,编译的时候你还是得老老实实的写安全型的程序。那这样的程序岂不是不能调试了?当然不行,所以还得再开一条后路,让他在调试的时候也能乖乖的运行。

      既然要给调试时留条后路,自然就要用到条件编译指令。在工程->属性->生成的条件编译参数里面,填上DEBUG_ = 1,然后再修改程序:

Option Explicit

Declare Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" (Destination As Any, Source As Any, ByVal Length As Long)

Dim BASE As Long

#If DEBUG_ Then
    Property Get MEM(ByVal Addr As Long) As Byte
        Call CopyMemory(MEM, ByVal Addr, 1)
    End Property
    
    Property Let MEM(ByVal Addr As Long, ByVal val As Byte)
        Call CopyMemory(ByVal Addr, val, 1)
    End Property
#Else
    Dim MEM(0) As Byte
#End If


Sub Main()
    Dim src As Byte
    Dim pValue As Long

#If DEBUG_ Then
#Else
    BASE = -VarPtr(MEM(0))
#End If

    src = 123
    pValue = VarPtr(src)
    
    MsgBox MEM(BASE + pValue)
End Sub


      这里增加了一个名为MEM的属性过程,在调试过程中冒充那个MEM的数组,用CopyMemory来实现内存的访问。不过可要注意啦:调试时比编译后运行要慢上15倍之多!可见CopyMemory的开销确实不容乐观。

      想必大家都在想一个问题,这样仅仅是在访问字节型的指针变量,能不能访问Long或更多的。答案当然是可以的,不过程序的风格可能变得很丑陋,例如MEM(BASE + pValue/4),因为MEM是Long型的了,每个元素都是4字节,不再想Byte()那样直接访问了。

不过当初考虑这个方法仅仅为了访问字节流而已,屡试不爽。

点击查看更多内容
2人点赞

若觉得本文不错,就分享一下吧!

评论

作者其他优质文章

正在加载中
感谢您的支持,我会继续努力的~
扫码打赏,你说多少就多少
赞赏金额会直接到老师账户
支付方式
打开微信扫一扫,即可进行扫码打赏哦
今天注册有机会得

100积分直接送

付费专栏免费学

大额优惠券免费领

立即参与 放弃机会
意见反馈 帮助中心 APP下载
官方微信

举报

0/150
提交
取消