sizeof? is there a .NET equivalent

S

stand__sure

Having recently had a need to use ZeroMemory from the kernel32.dll, I
"discovered" that there is apparently no .NET equivalent to the c/c++ sizeof
operator -- one does exist in the Marshall namespace, but it fails when
passed a managed type. I poked around the Reflection namespace, but found
nothing that fits the bill. Is there a runtime equivalent to sizeof in
..NET?
 
L

Larry Lard

stand__sure said:
Having recently had a need to use ZeroMemory from the kernel32.dll, I
"discovered" that there is apparently no .NET equivalent to the c/c++ sizeof
operator -- one does exist in the Marshall namespace, but it fails when
passed a managed type. I poked around the Reflection namespace, but found
nothing that fits the bill. Is there a runtime equivalent to sizeof in
.NET?

Hmm well if Marshal.SizeOf is no good for you, how about Len(Object)?
 
C

Crouchie1998

This is taken from something I have coded in the past:

Private Declare Sub ZeroMemory Lib "kernel32.dll" Alias "RtlZeroMemory" _
(ByVal Destination As String, ByVal Length As Integer)

ZeroMemory(txtPassword.Text, txtPassword.Text.Length * 2)

-------------------

The Marshall.SizeOf is here:

System.Runtime.InteropServices.Marshal

I hope this helps

Crouchie1998
BA (HONS) MCP MCSE
 
S

stand__sure

Thanks for the reply -- I did end up using this approach -- my objection to
it is that it returns the number of bytes for everything but strings, in
which case it returns the number of characters (necessitating a
multiplication step for only this type -- this is manageable but seems like
a wasteful step -- something like LenB would be useful, but it has been
deprecated)
 
S

stand__sure

here's the solution

Protected Overrides Sub Finalize()

MyBase.Finalize()

Dim nbytes As Integer = sizeof(deskey)

ZeroMemory(gch.AddrOfPinnedObject, nbytes)

gch.Free()

End Sub

Public Function sizeof(Of T As IList)(ByVal arrobj As T) As Integer

Dim myEnum As IEnumerator = arrobj.GetEnumerator()

myEnum.MoveNext()

Dim nBaseBytes As Integer = Len(myEnum.Current())

Dim nElements As Integer = arrobj.Count

Return (nBaseBytes * nElements)

End Function
 
H

Herfried K. Wagner [MVP]

Crouchie1998 said:
This is taken from something I have coded in the past:

Private Declare Sub ZeroMemory Lib "kernel32.dll" Alias "RtlZeroMemory" _
(ByVal Destination As String, ByVal Length As Integer)

ZeroMemory(txtPassword.Text, txtPassword.Text.Length * 2)

That's a very bad idea because strings are immutable in .NET and thus the
string object may become dysfunctional.
 
S

stand__sure

it's "do-able" if you obtain a pinned GCHandle.

as in
ZeroMemory(gch.AddrOfPinnedObject, nbytes)
gch.Free()
 
S

stand__sure

the code above had some problems, here's a better snippet (I have partially
tested it -- it handles empty arrays properly, as well as, regular n-dim
arrays -- it does not work for jagged arrays... it will work for arrays of
arrays, but I am doubtful that it would be useful in a ZeroMemory scenario
since the allocated regions are not contiguous)

''' <summary>

''' Gets true size of the array.

''' </summary>

''' <typeparam name="T">A Type that derives from IList, e.g.
Array</typeparam>

''' <param name="arrobj">The array object</param>

''' <returns>Integer representing size of object in bytes</returns>

''' <remarks>generics in VB! NOT tested for n-dimensional arrays</remarks>

Private Function sizeofarray(Of T As IList)(ByVal arrobj As T) As Integer

'a clean way to get the first item -- LowerBound may not be zero

Dim myEnum As IEnumerator = arrobj.GetEnumerator()

'get number of elements

Dim nElements As Integer = arrobj.Count

Dim nBaseBytes As Integer = 1 'size in bytes of an element

'(default to 1 for empty case

'initial position is before first element

If (myEnum.MoveNext()) Then 'if zero-length array this will eveluate to
false

'get size in bytes of an element

nBaseBytes = sizeof(myEnum.Current())

End If

'return result

Return (nBaseBytes * nElements)

End Function

Public Function sizeof(Of T)(ByVal obj As t) As Integer

If (obj.GetType.IsArray) Then

Return (sizeofarray(DirectCast(obj, IList)))

Else

If (obj.GetType Is GetType(String)) Then

Return (sizeof(obj.ToString().ToCharArray()))

Else

Return (Len(obj))

End If

End If

End Function
 
H

Herfried K. Wagner [MVP]

stand__sure said:
it's "do-able" if you obtain a pinned GCHandle.

I assume that the string will be pinned automatically. However, there is
still no guarantee that all of the string object's methods and properties
will work as expected after manipulating the string.
 
J

Jay B. Harlow [MVP - Outlook]

strand,
| it's "do-able" if you obtain a pinned GCHandle.
Just because you can do something, doesn't really mean you should do
something.

Strings are Immutable! Period. Although it appears to work, IMHO you are
"Programming by Coincidence"
http://www.pragmaticprogrammer.com/ppbook/extracts/coincidence.html!

The framework knows that strings are immutable, so it can have multiple
string variables point to the same string object (aliasing). Which is good
as it may reduce the amount memory being used. Its bad, as your code is
assuming that it is changing a specific string variable, where as it may be
changing multiple string variables...

For example:

Dim s1 As String = "Hello World"
Dim s2 As String = s2

ZeroMemory(s1, s1.Length * 2)
Debug.WriteLine(s1, "s1")
Debug.WriteLine(s2, "s2")


Notice that both s1 & s2 were filled with zeros!

If you want to zero strings, then I suggest you check out the SecureString
class in VS.NET 2005 (aka Whidbey, due out later in 2005)

SecureString:
http://msdn2.microsoft.com/library/7kt014s1(en-us,vs.80).aspx

VS.NET 2005:
http://lab.msdn.microsoft.com/vs2005/

Attempting to zero (using ZeroMemory) out any object is "dangerous" at best
as only the runtime itself really knows how objects are laid out in memory,
& calling ZeroMemory may destabilize the runtime, at worst it will cause
obscure errors later in your program, at best your program will end
immediately. NOTE: The 64-bit & 32-bit frameworks may layout objects
differently as may 1.0, 1.1, & 2.0 themselves...

Also, using ZeroMemory "safely" with the GC is "wishful" thinking. As the
object may actually have moved, multiple times between the time it was
created & when you call ZeroMemory. Which means that although you may have
zeroed the objects final resting place, that it stopped at other places in
memory first... Those other places in memory may still be visible... I would
expect a class such as System.Buffer to have a "block fill" method, however
I do not see one, as System.Buffer would "know" about the layout of the
memory & zero that memory in a runtime friendly manner...



Hope this helps
Jay




| it's "do-able" if you obtain a pinned GCHandle.
|
| as in
| ZeroMemory(gch.AddrOfPinnedObject, nbytes)
| gch.Free()
|
| | >> This is taken from something I have coded in the past:
| >>
| >> Private Declare Sub ZeroMemory Lib "kernel32.dll" Alias "RtlZeroMemory"
_
| >> (ByVal Destination As String, ByVal Length As Integer)
| >>
| >> ZeroMemory(txtPassword.Text, txtPassword.Text.Length * 2)
| >
| > That's a very bad idea because strings are immutable in .NET and thus
the
| > string object may become dysfunctional.
| >
| > --
| > M S Herfried K. Wagner
| > M V P <URL:http://dotnet.mvps.org/>
| > V B <URL:http://classicvb.org/petition/>
|
|
 
C

c anderson

the pinning/zeroing approach was shown in a KB article on encrypting
files (http://support.microsoft.com/default.aspx?scid=kb;en-us;301070 or
ms-help://MS.VSCC.v80/MS.MSDNQTR.v80.en/MS.MSDN.v80/MS.KB.v10.en/enu_kbv
bnetkb/vbnetkb/301070.htm)

I was actually using it on a byte array and not on a string. So, the
issue about bstr storage hadn't yet arisen -- it would have eventually
since I have some read-only properties that return sensitive data, pass
keys in constructors, &c. the SecureString call looks like a good fit
for this and I am grateful for the suggestion.

the posted question about a sizeof operator arose from looking at how
len(object) works -- it behaves as a byte count for most types, as a
length for strings (necessitating a 2*len(strvar)), and fails for an
array type.

the sizeof routines are where my focus has been and I would appreciate
comments on those -- current versions are appended to the end of this
post. the approach handles zero-length arrays, n-dimension regular
arrays (behavior in a ZeroMemory scenario has NOT been tested yet), and
arrays of arrays (this last was by happenstance and would be of no use
in a ZeroMemory scenario -- how to differentiate between this and
n-dimensional is unclear). jagged arrays fail (but I am uncertain as to
how to catch these without diving into each element -- in which case I
could compute a size). there are other cases in which it use makes no
sense, but these would be logical bugs on the part of the developer
using the functions (e.g. an array of generic objects that resolve to
other types -- obviously the size of the object array would not be
meaningful)
 
J

Jay B. Harlow [MVP - Outlook]

C Anderson.
| the pinning/zeroing approach was shown in a KB article on encrypting
| files (http://support.microsoft.com/default.aspx?scid=kb;en-us;301070 or
| ms-help://MS.VSCC.v80/MS.MSDNQTR.v80.en/MS.MSDN.v80/MS.KB.v10.en/enu_kbv
| bnetkb/vbnetkb/301070.htm)
As I stated, the GC can move the string, ergo you are only zeroing the last
copy of the string, not each time the string moved. Also you may be working
with an alias of the string. Which may or may not be a problem.

Further the "contract" for a string states it is immutable, going behind the
frameworks back to change it is "Breaking the contract".

| I was actually using it on a byte array and not on a string. So, the
| issue about bstr storage hadn't yet arisen
System.String storage <> BSTR storage. System.String is stored in the .NET
heap (its a .NET object). BSTR is stored in a COM heap (its a COM object).
Although both hold "strings", both are very different objects...

A byte array is a reference type, if you assign the array to other variables
you can have duplicates (aka aliasing) again this may or may not be a
problem...

Keith Brown's book "The .NET Developer's Guide to Windows Security" from
Addison Wesley contains a plethora of information on security under Win32 &
specifically .NET. I want to say it included a discussion of "zeroing"
memory. You can access the book on-line at:
http://www.pluralsight.com/keith/book/html/book.html, unfortunately I don't
remember which topics discussed "zeroing" memory.


| the sizeof routines are where my focus has been and I would appreciate
| comments on those
The runtime knows how objects are laid out. This layout can change & does
change between version of the framework. (1.0, 1.1, 2.0, 32-bit, 64-bit) I
sincerely wish you luck on "defining" a consistent "algorithm" for a managed
SizeOf. Unfortunately I don't have links handy to blogs that discuss the
layout changes... I can look if you like.

Hope this helps
Jay



|
| the pinning/zeroing approach was shown in a KB article on encrypting
| files (http://support.microsoft.com/default.aspx?scid=kb;en-us;301070 or
| ms-help://MS.VSCC.v80/MS.MSDNQTR.v80.en/MS.MSDN.v80/MS.KB.v10.en/enu_kbv
| bnetkb/vbnetkb/301070.htm)
|
| I was actually using it on a byte array and not on a string. So, the
| issue about bstr storage hadn't yet arisen -- it would have eventually
| since I have some read-only properties that return sensitive data, pass
| keys in constructors, &c. the SecureString call looks like a good fit
| for this and I am grateful for the suggestion.
|
| the posted question about a sizeof operator arose from looking at how
| len(object) works -- it behaves as a byte count for most types, as a
| length for strings (necessitating a 2*len(strvar)), and fails for an
| array type.
|
| the sizeof routines are where my focus has been and I would appreciate
| comments on those -- current versions are appended to the end of this
| post. the approach handles zero-length arrays, n-dimension regular
| arrays (behavior in a ZeroMemory scenario has NOT been tested yet), and
| arrays of arrays (this last was by happenstance and would be of no use
| in a ZeroMemory scenario -- how to differentiate between this and
| n-dimensional is unclear). jagged arrays fail (but I am uncertain as to
| how to catch these without diving into each element -- in which case I
| could compute a size). there are other cases in which it use makes no
| sense, but these would be logical bugs on the part of the developer
| using the functions (e.g. an array of generic objects that resolve to
| other types -- obviously the size of the object array would not be
| meaningful)
|
|
 
C

c j anderson, mcp

for the current version of sizeof, please see
http://stand__sure.aspfreeserver.com/sizeof/utility.vb.html

Jay B. Harlow [MVP - Outlook]...
As I stated, the GC can move the string, ergo you are only zeroing the
last copy of the string, not each time the string moved.

Correct. In the byte case, I pinned the object immediately. I would
recommend doing the same for a string. Pinned objects are NOT moved by
the GC.
A byte array is a reference type, if you assign the array to other
variables you can have duplicates (aka aliasing) again this may or may
not be a problem...

valid point. my usage of ZeroMemory was in a class destructor and was
acting on a private member variable. all that really mattered was that
memory space not contain any meaningful data. I see no clean way to
overcome the paging issue -- possibly throwing a Monitor or a SyncLock
on it would keep it volatile... unless there is a VB equiv of the
c/c++/c# keyword volatile...
Keith Brown's book "The .NET Developer's Guide to Windows Security"...

thank you -- excellent link!
 
J

Jay B. Harlow [MVP - Outlook]

| Correct. In the byte case, I pinned the object immediately. I would
| recommend doing the same for a string. Pinned objects are NOT moved by
| the GC.
Exactly!

My concern with pinning the object immediately is you now placed pressure on
the GC, because you indicated this object is pinned the GC is not able to
move it, ergo the GC has to work around it. I understand this "working
around it" causes the GC to work less optimally.

See "Pinning" at:
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dnpag/html/scalenetchapt05.asp


Other links on Pinned object, & GC performance:
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dnpag/html/scalenetchapt07.asp

http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dnpag/html/scalenetchapt15.asp

http://msdn.microsoft.com/library/d...y/en-us/dndotnet/html/highperfmanagedapps.asp


Hope this helps
Jay

| for the current version of sizeof, please see
| http://stand__sure.aspfreeserver.com/sizeof/utility.vb.html
|
| Jay B. Harlow [MVP - Outlook]...
| >As I stated, the GC can move the string, ergo you are only zeroing the
| last copy of the string, not each time the string moved.
|
| Correct. In the byte case, I pinned the object immediately. I would
| recommend doing the same for a string. Pinned objects are NOT moved by
| the GC.
|
| >A byte array is a reference type, if you assign the array to other
| variables you can have duplicates (aka aliasing) again this may or may
| not be a problem...
|
| valid point. my usage of ZeroMemory was in a class destructor and was
| acting on a private member variable. all that really mattered was that
| memory space not contain any meaningful data. I see no clean way to
| overcome the paging issue -- possibly throwing a Monitor or a SyncLock
| on it would keep it volatile... unless there is a VB equiv of the
| c/c++/c# keyword volatile...
|
| >Keith Brown's book "The .NET Developer's Guide to Windows Security"...
|
| thank you -- excellent link!
| ---
| http://code.box.sk
| nemo me impune lacessit
|
|
 
J

Jay B. Harlow [MVP - Outlook]

C J Anderson,
Here's another article about SecureString.

http://msdn.microsoft.com/msdnmag/issues/05/01/SecurityBriefs/

Hope this helps
Jay

| for the current version of sizeof, please see
| http://stand__sure.aspfreeserver.com/sizeof/utility.vb.html
|
| Jay B. Harlow [MVP - Outlook]...
| >As I stated, the GC can move the string, ergo you are only zeroing the
| last copy of the string, not each time the string moved.
|
| Correct. In the byte case, I pinned the object immediately. I would
| recommend doing the same for a string. Pinned objects are NOT moved by
| the GC.
|
| >A byte array is a reference type, if you assign the array to other
| variables you can have duplicates (aka aliasing) again this may or may
| not be a problem...
|
| valid point. my usage of ZeroMemory was in a class destructor and was
| acting on a private member variable. all that really mattered was that
| memory space not contain any meaningful data. I see no clean way to
| overcome the paging issue -- possibly throwing a Monitor or a SyncLock
| on it would keep it volatile... unless there is a VB equiv of the
| c/c++/c# keyword volatile...
|
| >Keith Brown's book "The .NET Developer's Guide to Windows Security"...
|
| thank you -- excellent link!
| ---
| http://code.box.sk
| nemo me impune lacessit
|
|
 
C

c j anderson, mcp

Excellent links -- I was not aware that the existence of a destructor
caused an object to live for an extra generation... some fantastic
stuff in there.

thanks again.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top