What Is the Equivalent of Memset in C#

Equivalent of memset in C# unsafe code

Well, there is... memset. Why settle for a replacement when you can p/invoke the real thing?

[DllImport("msvcrt.dll", EntryPoint = "memset", CallingConvention = CallingConvention.Cdecl, SetLastError = false)]
public static extern IntPtr MemSet(IntPtr dest, int c, IntPtr count);

Taken from pinvoke.net

edit

As @Hans rightfully mentions in the OP comments, this is useless if you don't already know the size of *buffer.

Passing byte[] as IntPtr by PInvoke to memset

Your code is fine and will work correctly.

It would be perfectly reasonable, and much clearer in my view, to avoid unsafe and declare the parameter to memset to be byte[]. I'd declare it like this:

[DllImport("msvcrt.dll", CallingConvention = CallingConvention.Cdecl)]
public static extern IntPtr memset(byte[] dest, int c, IntPtr count);

Note that the final parameter is size_t which is pointer sized.

I also do wonder why you are opting to do this at all in unmanaged code, but presumably you have your reasons.

How to quickly zero out an array?

Try Array.Clear():

Sets a range of elements in the Array
to zero, to false, or to
null
(Nothing in Visual Basic), depending
on the element type.

c# cannot execute c++ dll with memset inside


..., ref char result,int max_result_size,ref int realResultSize

The char* parameter is ambiguous in C and C++. Could mean a reference to a single char (ref char in C#) or a reference to an array (char[] in C#). That doesn't matter much in those languages, although you can certainly get it wrong the exact same way you got it wrong here, but it makes a big, big difference in C#. You get it wrong in C by passing a char& instead of a char[]& and the memset() call will corrupt the stack of the caller. Same thing happens here.

Since the pinvoke marshaller doesn't know that it should actually pass an array reference, and the char type is not compatible with C code since it is 2 bytes in C# and 1 byte in C, the marshaller makes a copy of the single char to convert it to byte. Your memset() call now corrupts the memory allocated by the pinvoke marshaller for that single byte. Outcome is quite unpredictable, you only get an AVE if you're lucky.

Something else it does not know is that it must copy the array back. Beyond not knowing it is an array, it also doesn't know its length. And you have to ask for it, by default the pinvoke marshaller doesn't copy arrays back to avoid the cost of doing so.

Telling the pinvoke marshaller that it is an array that needs to be copied back looks like this:

..., [Out][MarshalAs(UnmanagedType.LPArray, SizeParamIndex(6)] char[] result

The [Out] attribute asks for array elements to be copied back, the SizeParamIndex property says where to look when the marshaller needs to know how many elements need to be copied.

It is both simpler and more efficient by not forcing the pinvoke marshaller to convert the array elements:

..., byte[] result

No longer a need to help with the [Out] and [MarshalAs] attribute. Since no conversion is required anymore, the pinvoke marshaller can simply pin the array and pass a pointer to its first element. Your C code now writes directly to the GC heap storage. Good thing you have the max_result_size argument, it is very important to avoid GC heap corruption. Be sure to pass the array's Length property.

Note that the same story applies to the data and info parameters. Not nearly as fatal since they don't require conversion. Declare them as double[] instead, no ref.

Fastest way in c# to clear portions of an array or move portions around

An array in c# will already be allocated with the default value of the type, so memset to 0 is usually irrelevant. You will never get a "dirty" array on construction.

For copy operations, you can use Array.Copy for typed copying or Buffer.Blockcopy for raw byte copying.

Both of these support copying from/to the same array, you just have to be careful not to provide overlapping idices.

Edit:

For clearing out data you can use Array.Clear

Initialize a byte array to a certain value, other than the default null?

For small arrays use array initialisation syntax:

var sevenItems = new byte[] { 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20 };

For larger arrays use a standard for loop. This is the most readable and efficient way to do it:

var sevenThousandItems = new byte[7000];
for (int i = 0; i < sevenThousandItems.Length; i++)
{
sevenThousandItems[i] = 0x20;
}

Of course, if you need to do this a lot then you could create a helper method to help keep your code concise:

byte[] sevenItems = CreateSpecialByteArray(7);
byte[] sevenThousandItems = CreateSpecialByteArray(7000);

// ...

public static byte[] CreateSpecialByteArray(int length)
{
var arr = new byte[length];
for (int i = 0; i < arr.Length; i++)
{
arr[i] = 0x20;
}
return arr;
}

Why do ZeroMemory, etc. exist when there are memset, etc. already?

In C and C++, ZeroMemory() and memset() are the exact same thing.

/* In winnt.h */
#define RtlZeroMemory(Destination,Length) memset((Destination),0,(Length))

/* In winbase.h */
#define ZeroMemory RtlZeroMemory

Why use ZeroMemory() then? To make it obvious. But I prefer memset() in C or C++ programs.

Is there a quick way of zeroing a struct in C#?

Just use:

myLunch = new ChocolateBar();

or

myLunch = default(ChocolateBar);

or

myLunch = default;

These are equivalent1, and will both end up assigning a new "all fields set to zero" value to myLunch.

Also, ideally don't use mutable structs to start with - I typically prefer to create a struct which is immutable, but which has methods which return a new value with a particular field set differently, e.g.

ChocolateBar myLunch = new ChocolateBar().WithLength(100).WithGirth(10);

... and of course provide appropriate constructors as well:

ChocolateBar myLunch = new ChocolarBar(100, 10);

1 At least for structs declared in C#. Value types can have custom parameterless constructors in IL, but it's relatively hard to predict the circumstances in which the C# compiler will call that rather than just use the default "zero" value.



Related Topics



Leave a reply



Submit