目次→
演算子→
メモリ演算子→
Operator New Overload←オリジナル・サイト
UDT(User Defined Type)に適用するときに
演算子 New 式 によって提供される動的メモリー割り当て処理部分を多重定義するための、メンバー演算子。
構文:
パラメータ:
戻り値:
新しく割り当てられたメモリの先頭への
any ptr 型のポインタ。
記述:
メンバ演算子
New Overload は、UDT(User Defined Type)に適用するとき、
New Expression 演算子によって提供される動的メモリ割り当て処理部分を、多重定義します。
したがって、ユーザーは、独自の動的メモリー割り当てプロセス部分を定義できます。
しかしその後、
New Expression 演算子によって提供される UDT インスタンス構築プロセス部分は、変更されません。
New[] Overload 演算子は、
New Overload 演算子の(1次元)配列バージョンであり、UDT(ユーザー定義型 (User Defined Type))に適用するときに、
New[] Expression 演算子によって提供される、動的メモリ割り当てプロセスを、多重定義します。
New Overload 演算子を使って割り振られたメモリーは、また、
Delete Overload 演算子を定義して解放する必要があります。
New[] Overload 演算子で割り当てられたメモリは、また、
Delete[] Overload 演算子(
Delete Overload 演算子の配列バージョン)を定義することによって解放する必要があります。
異なるバージョンの演算子を混在させることはできません。
メンバー演算子
New Overload、および
New[] Overload は、明示的に宣言されていなくても常に静的です。(
staticキーワードは不要ですが、使うことはできます。)
したがって、暗黙の
This インスタンス引数が渡されることはありません。(インスタンスはまだ構築されていないため。)
例:
メンバ演算子 "New([])Overload" と "Delete([])Overload" を使った、UDT 用の動的割り当て表示プログラム
(非常に単純な例、構文の使用だけ):
- メモリ割り当てを表示:アドレス、サイズ
- メモリ割り当て解除を表示:アドレス
Type UDTdisplayer
'' user UDT fields:
Dim As Byte b(1 To 1024*1024)
'' display fields:
Public:
Declare Operator New (ByVal size As UInteger) As Any Ptr
Declare Operator Delete (ByVal buf As Any Ptr)
Declare Operator New[] (ByVal size As UInteger) As Any Ptr
Declare Operator Delete[] (ByVal buf As Any Ptr)
Private:
Declare Static Function allocation (ByRef N As String, ByVal size As UInteger) As Any Ptr
Declare Static Sub deallocation (ByRef D As String, ByVal p As Any Ptr)
End Type
Operator UDTdisplayer.New (ByVal size As UInteger) As Any Ptr
Return UDTdisplayer.allocation("New", size)
End Operator
Operator UDTdisplayer.Delete (ByVal buf As Any Ptr)
UDTdisplayer.deallocation("Delete", buf)
End Operator
Operator UDTdisplayer.New[] (ByVal size As UInteger) As Any Ptr
Return UDTdisplayer.allocation("New[]", size)
End Operator
Operator UDTdisplayer.Delete[] (ByVal buf As Any Ptr)
UDTdisplayer.deallocation("Delete[]", buf)
End Operator
Function UDTdisplayer.allocation (ByRef N As String, ByVal size As UInteger) As Any Ptr
Dim As Any Ptr p = Allocate(size)
Print "memory allocation for " & size & " bytes from '" & N & "' at address: " & p
Return p
End Function
Sub UDTdisplayer.deallocation (ByRef D As String, ByVal p As Any Ptr)
Print "memory deallocation from '" & D & "' at address " & p
Deallocate p
End Sub
Randomize
Dim As UDTdisplayer Ptr pu1 = New UDTdisplayer
Dim As UDTdisplayer Ptr pu2 = New UDTdisplayer[3]
Delete pu1
Delete[] pu2
Sleep
出力例(アドレスが対応している点が重要):
memory allocation for 1048576 bytes from 'New' at address: 32677920
memory allocation for 3145728 bytes from 'New[]' at address: 33775648
memory deallocation from 'Delete' at address 32677920
memory deallocation from 'Delete[]' at address 33775648
メモリを整列配置するプログラム:
-
メンバ演算子 "New Overload" と "Delete Overload" を使うことで、作成された User オブジェクトは "ALIGN" バイトの倍数(この例では256バイト)に整列されます。
- 割り当てられたメモリの実ポインタは、パディングブロック内の、User ポインタのすぐ上に保存されます。
Const ALIGN = 256
Type UDT
Dim As Byte a(0 To 10 * 1024 * 1024 - 1) '' 10 megabyte fixed array
Declare Operator New (ByVal size As UInteger) As Any Ptr
Declare Operator Delete (ByVal buffer As Any Ptr)
Declare Constructor ()
Declare Destructor ()
End Type
Operator UDT.New (ByVal size As UInteger) As Any Ptr
Print " Overloaded New operator, with parameter size = &h" & Hex(size)
Dim pOrig As Any Ptr = CAllocate(ALIGN-1 + SizeOf(UDT Ptr) + size)
Dim pMin As Any Ptr = pOrig + SizeOf(UDT Ptr)
Dim p As Any Ptr = pMin + ALIGN-1 - (CUInt(pMin + ALIGN-1) Mod ALIGN)
Cast(Any Ptr Ptr, p)[-1] = pOrig
Operator = p
Print " real pointer = &h" & Hex(pOrig), "return pointer = &h" & Hex(p)
End Operator
Operator UDT.Delete (ByVal buffer As Any Ptr)
Print " Overloaded Delete operator, with parameter buffer = &h" & Hex(buffer)
Dim pOrig As Any Ptr = Cast(Any Ptr Ptr, buffer)[-1]
Deallocate(pOrig)
Print " real pointer = &h" & Hex(pOrig)
End Operator
Constructor UDT ()
Print " Constructor, @This = &h" & Hex(@This)
End Constructor
Destructor UDT ()
Print " Destructor, @This = &h" & Hex(@This)
End Destructor
Print "'Dim As UDT Ptr p = New UDT'"
Dim As UDT Ptr p = New UDT
Print " p = &h" & Hex(p)
Print "'Delete p'"
Delete p
Sleep
出力例:
'Dim As UDT Ptr p = New UDT'
Overloaded New operator, with parameter size = &hA00000
real pointer = &h420020 return pointer = &h420100
Constructor, @This = &h420100
p = &h420100
'Delete p'
Destructor, @This = &h420100
Overloaded Delete operator, with parameter buffer = &h420100
real pointer = &h420020
メンバー演算子 "New [] Overload" および "Delete [] Overload" を使った、UDT用の動的割り当てマネージャ:
-
メモリ割り当て/割り当て解除の監視:アドレス、サイズ、使用されているメモリの合計
-
異常な割り当て解除要求の検出
-
失敗した割り当ての検出(Allocate() が null ポインタを返す)
-
しきい値を超える合計割り当てメモリサイズを検出
-
上の最後の2つの検出ケースでは、プログラムの強制終了の前に、自動的にメモリが解放されます。
動作原理は、要求されたサイズで、割り当てられたアドレスを含む、まだ解放されていない成功した割り当ての、動的リストを管理することです:
Type UDTmanager
'' user UDT fields:
Dim As Byte b(1 To 1024*1024)
'' manager fields:
Public:
Declare Operator New[] (ByVal size As UInteger) As Any Ptr
Declare Operator Delete[] (ByVal buf As Any Ptr)
Static As UInteger maxmemory
Private:
Static As Any Ptr address()
Static As UInteger bytes()
Static upbound As UInteger
Declare Static Function printLine (ByRef text As String, ByVal index As UInteger, ByVal sign As Integer) As UInteger
Declare Static Sub endProgram ()
End Type
Dim As UInteger UDTmanager.maxmemory = 3 * 1024 * 1024 * 1024
ReDim UDTmanager.address(0)
ReDim UDTmanager.bytes(0)
Dim UDTmanager.upbound As UInteger = 0
Function UDTmanager.printLine (ByRef text As String, ByVal index As UInteger, ByVal sign As Integer) As UInteger
Dim As UInteger total = 0
For I As UInteger = 1 To UDTmanager.upbound
If I <> index OrElse Sgn(sign) > 0 Then
total += UDTmanager.bytes(I)
End If
Next I
Print text, "&h" & Hex(UDTmanager.address(index), SizeOf(Any Ptr) * 2),
If sign <> 0 Then
Print Using " +####.## MB"; Sgn(sign) * Cast(Integer, UDTmanager.bytes(index) / 1024) / 1024;
Else
Print Using "( ####.## MB)"; UDTmanager.bytes(index) / 1024 / 1024;
End If
Print,
Print Using "###.## GB"; total / 1024 / 1024 / 1024
Return total
End Function
Sub UDTmanager.endProgram ()
Do While UDTmanager.upbound > 0
Deallocate UDTmanager.address(UDTmanager.upbound)
UDTmanager.printLine("memory deallocation forced", UDTmanager.upbound, -1)
UDTmanager.upbound -= 1
ReDim Preserve UDTmanager.address(UDTmanager.upbound)
ReDim Preserve UDTmanager.bytes(UDTmanager.upbound)
Loop
Print "end program forced"
Print
Sleep
End
End Sub
Operator UDTmanager.New[] (ByVal size As UInteger) As Any Ptr
Dim As Any Ptr p = Allocate(size)
If p > 0 Then
UDTmanager.upbound += 1
ReDim Preserve UDTmanager.address(UDTmanager.upbound)
ReDim Preserve UDTmanager.bytes(UDTmanager.upbound)
UDTmanager.address(UDTmanager.upbound) = p
UDTmanager.bytes(UDTmanager.upbound) = size
If UDTmanager.printLine("memory allocation", UDTmanager.upbound, +1) > UDTmanager.maxmemory Then
UDTmanager.address(0) = p
UDTmanager.bytes(0) = size
Print
UDTmanager.printLine("memory allocation exceeded", 0, 0)
UDTmanager.endProgram()
End If
Return p
Else
UDTmanager.address(0) = p
UDTmanager.bytes(0) = size
Print
UDTmanager.printLine("memory allocation failed", 0, 0)
UDTmanager.endProgram()
End If
End Operator
Operator UDTmanager.Delete[] (ByVal buf As Any Ptr)
Dim As UInteger found = 0
For I As UInteger = 1 To UDTmanager.upbound
If UDTmanager.address(I) = buf Then
Deallocate buf
UDTmanager.printLine("memory deallocation", I, -1)
For J As UInteger = I + 1 To UDTmanager.upbound
UDTmanager.address(J - 1) = UDTmanager.address(J)
UDTmanager.bytes(J - 1) = UDTmanager.bytes(J)
Next J
UDTmanager.upbound -= 1
ReDim Preserve UDTmanager.address(UDTmanager.upbound)
ReDim Preserve UDTmanager.bytes(UDTmanager.upbound)
found = 1
Exit For
End If
Next I
If found = 0 Then
UDTmanager.address(0) = buf
UDTmanager.bytes(0) = 0
UDTmanager.printLine("deallocation not matching", 0, 0)
End If
End Operator
Print "Message",, "Address" & Space(SizeOf(Any Ptr)), "Size", "Total"
Print
Randomize
Dim As UDTmanager Ptr pu1 = New UDTmanager[CUInt(Rnd() * 256 + 1)]
Dim As UDTmanager Ptr pu2 = New UDTmanager[CUInt(Rnd() * 256 + 1)]
Dim As UDTmanager Ptr pu3 = Cast(UDTmanager Ptr, 1)
Delete[] pu2
Delete[] pu3
Delete[] pu2
Delete[] pu1
Do
Dim As UDTmanager Ptr pu = New UDTmanager[CUInt(Rnd() * 512 + 1)]
Loop
fbc 32ビット用の出力(最大動的データ < 2 GB)。
ここでは、メモリ割り当てが失敗したため、プログラムは停止しています:
Message Address Size Total
memory allocation &h020E0020 +99.00 MB 0.10 GB
memory allocation &h083F3020 +3.00 MB 0.10 GB
memory deallocation &h083F3020 -3.00 MB 0.10 GB
deallocation not matching &h00000001 ( 0.00 MB) 0.10 GB
deallocation not matching &h083F3020 ( 0.00 MB) 0.10 GB
memory deallocation &h020E0020 -99.00 MB 0.00 GB
memory allocation &h020ED020 +103.00 MB 0.10 GB
memory allocation &h087F2020 +106.00 MB 0.20 GB
memory allocation &h0F20D020 +230.00 MB 0.43 GB
memory allocation &h1D812020 +137.00 MB 0.56 GB
memory allocation &h2612C020 +377.00 MB 0.93 GB
memory allocation &h3DA30020 +275.00 MB 1.20 GB
memory allocation &h4ED40020 +220.00 MB 1.41 GB
memory allocation &h5C958020 +229.00 MB 1.64 GB
memory allocation failed &h00000000 ( 142.00 MB) 1.64 GB
memory deallocation forced &h5C958020 -229.00 MB 1.41 GB
memory deallocation forced &h4ED40020 -220.00 MB 1.20 GB
memory deallocation forced &h3DA30020 -275.00 MB 0.93 GB
memory deallocation forced &h2612C020 -377.00 MB 0.56 GB
memory deallocation forced &h1D812020 -137.00 MB 0.43 GB
memory deallocation forced &h0F20D020 -230.00 MB 0.20 GB
memory deallocation forced &h087F2020 -106.00 MB 0.10 GB
memory deallocation forced &h020ED020 -103.00 MB 0.00 GB
end program forced
fbc 64ビット用の出力(最大動的データ < 仮想メモリ)。
ここでは、合計割り当てメモリサイズ > 3 GB(調整可能しきい値)のため、プログラムが停止します。
Message Address Size Total
memory allocation &h0000000001EA5040 +105.00 MB 0.10 GB
memory allocation &h00000000087BC040 +93.00 MB 0.19 GB
memory deallocation &h00000000087BC040 -93.00 MB 0.10 GB
deallocation not matching &h0000000000000001 ( 0.00 MB) 0.10 GB
deallocation not matching &h00000000087BC040 ( 0.00 MB) 0.10 GB
memory deallocation &h0000000001EA5040 -105.00 MB 0.00 GB
memory allocation &h0000000001EA1040 +155.00 MB 0.15 GB
memory allocation &h000000000B9BF040 +165.00 MB 0.31 GB
memory allocation &h0000000015ED8040 +382.00 MB 0.69 GB
memory allocation &h000000002DCE7040 +458.00 MB 1.13 GB
memory allocation &h000000004A6FB040 +255.00 MB 1.38 GB
memory allocation &h000000005A607040 +96.00 MB 1.48 GB
memory allocation &h000000006061B040 +426.00 MB 1.89 GB
memory allocation &h000000007FFF9040 +221.00 MB 2.11 GB
memory allocation &h000000008DD03040 +119.00 MB 2.22 GB
memory allocation &h0000000095413040 +147.00 MB 2.37 GB
memory allocation &h000000009E727040 +217.00 MB 2.58 GB
memory allocation &h00000000AC03C040 +334.00 MB 2.91 GB
memory allocation &h00000000C0E4B040 +280.00 MB 3.18 GB
memory allocation exceeded &h00000000C0E4B040 ( 280.00 MB) 3.18 GB
memory deallocation forced &h00000000C0E4B040 -280.00 MB 2.91 GB
memory deallocation forced &h00000000AC03C040 -334.00 MB 2.58 GB
memory deallocation forced &h000000009E727040 -217.00 MB 2.37 GB
memory deallocation forced &h0000000095413040 -147.00 MB 2.22 GB
memory deallocation forced &h000000008DD03040 -119.00 MB 2.11 GB
memory deallocation forced &h000000007FFF9040 -221.00 MB 1.89 GB
memory deallocation forced &h000000006061B040 -426.00 MB 1.48 GB
memory deallocation forced &h000000005A607040 -96.00 MB 1.38 GB
memory deallocation forced &h000000004A6FB040 -255.00 MB 1.13 GB
memory deallocation forced &h000000002DCE7040 -458.00 MB 0.69 GB
memory deallocation forced &h0000000015ED8040 -382.00 MB 0.31 GB
memory deallocation forced &h000000000B9BF040 -165.00 MB 0.15 GB
memory deallocation forced &h0000000001EA1040 -155.00 MB 0.00 GB
end program forced
方言差:
QBからの違い:
参照: