人気ブログランキング | 話題のタグを見る
Excel VBAでメモリをダンプしてみる
■目的
ExcelVBAで変数のメモリをダンプしてみる。
これは非公開の関数を使用しているので、製品に組み込むような真似はすべきではない。


■コード

Option Explicit

#If VBA7 Then 'Office10 以降
Private Declare PtrSafe Sub RtlMoveMemory Lib "kernel32.dll" (ByVal Destination As Any, ByVal Source As Any, ByVal Length As LongPtr)
#Else ' Office 32-bit
Private Declare Sub RtlMoveMemory Lib "kernel32.dll" (ByVal Destination As Any, ByVal Source As Any, ByVal Length As Long)
#End If

#If VBA7 Then 'Office10 以降
Public Sub DumpMemory(ByVal offset As LongPtr, ByVal size As Long)
#Else ' Office 32-bit
Public Sub DumpMemory(ByVal offset As Long, ByVal size As Long)
#End If
ReDim data(1 To size) As Byte
Call RtlMoveMemory(VarPtr(data(1)), offset, size)
Dim i As Long
Dim j As Long
Dim hVal As String * 2
Dim add As String * 8

Dim ret As String
add = hex$(offset)
ret = add
For i = 1 To size
If j = 8 Then
j = 0
add = hex$(UnsignedAdd(offset, i))
ret = ret & vbCrLf & add
End If
hVal = hex$(data(i))
ret = ret & hVal & " "
j = j + 1
Next i
Debug.Print ret
End Sub
Private Function UnsignedAdd(ByVal Start As Long, ByVal Incr As Long) As Long
Const SignBit As Long = &H80000000
UnsignedAdd = (Start Xor SignBit) + Incr Xor SignBit
End Function


数値の変数の例:

Dim i As Long
i = 10
DumpMemory VarPtr(i), LenB(i)


出力結果

26F5D0 A 0 0 0

・・・0x000A すなわち10をあらわしている。


Stringの変数の例:

Dim s As String
s = "1あ3"
DumpMemory ByVal (StrPtr(s)), LenB(s)


59A590C 31 0 42 30 33 0

Unicodeのコード表と付き合わせると以下のようになる
http://ash.jp/code/unitbl21.htm
0x0031...UTF-16の「1」
0x3042...UTF-16の「あ」
0x0033...UTF-16の「3」


■説明
VBAでは基本的にポインタは使用できない。
だが、隠し関数として以下の3つが存在する

・VarPtr
変数のアドレスを返す

・StrPtr
UniCodeの文字列バッファのアドレスを返す
固定長の文字列を指定した場合、自動的に可変長の文字列を作成してそのアドレスを返す。
つまり、固定長の文字列に対しては使用すべきではない。

この挙動を確認するには次のコードを実行すればよい。

Dim fs As String * 5
Dim vs As String
fs = "12"
vs = "34"

Debug.Print "vs:" & hex$(StrPtr(vs)) & " fs:" & hex$(StrPtr(fs))
Debug.Print "vs:" & hex$(StrPtr(vs)) & " fs:" & hex$(StrPtr(fs))
Debug.Print "vs:" & hex$(StrPtr(vs)) & " fs:" & hex$(StrPtr(fs))

可変文字列の場合は、アドレスは変更されないが、固定文字列はStrPtrを実行するたびにそのアドレスが代わっているのが確認できる。

可変文字列と固定文字列は同じように見えるが、低レベルでメモリを操作する場合は根本的に違うということを認識しなければならない。




・ObjPtr
パラメーターとしてオブジェクト変数名を取得し、このオブジェクト変数によって参照されるインターフェイスのアドレスを取得する。


なお、配列のアドレスを取得したい場合はVarPtrArrayをせんげんして使用する

Private Declare Function VarPtrArray Lib "VBE7" Alias "VarPtr" (ByRef Var() As Any) As LongPtr

Dim a(0 To 10) As Byte
Debug.Print hex(VarPtrArray(a))

by mima_ita | 2013-06-19 06:48 | VBA
<< mimetexを試してみる tf-idfで文章の重み付けをする >>



実験ですお

by mima_ita
検索
カテゴリ
最新の記事
.NET4.5におけるasy..
at 2014-07-02 00:46
.NETでTwitterを検..
at 2014-06-29 00:49
Redmineのプラグインで..
at 2014-06-28 03:29
IO.popenのwrite..
at 2014-06-28 03:25
RedmineのWikiでU..
at 2014-06-28 03:16
以前の記事
最新のトラックバック
その他のジャンル
ブログパーツ